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
)
2864 struct PsdDevice
*pd
= pp
->pp_Device
;
2865 struct PsdDevice
*itpd
= pp
->pp_Device
;
2866 struct PsdConfig
*pc
;
2867 struct PsdInterface
*pif
;
2868 struct UsbStdDevDesc usdd
;
2871 ULONG oldnaktimeout
;
2881 BOOL haspopupinhibit
;
2885 struct PsdIFFContext
*pic
;
2890 #ifdef AROS_USB30_CODE
2891 struct UsbStdBOSDesc usbosd
;
2895 KPRINTF(2, ("psdEnumerateDevice(%p)\n", pp
));
2897 #ifdef AROS_USB2OTG_CODE
2898 struct PsdHardware
*phw
= pp
->pp_Device
->pd_Hardware
;
2900 if( !(phw
->phw_Capabilities
& UHCF_USB2OTG
) ) {
2902 Driver informs us that it is not USB2OTG device
2903 - Follow regular code path
2907 Driver informs us that it is USB2OTG device
2908 - Follow USB2OTG code path
2913 psdLockWriteDevice(pd
);
2914 if(pAllocDevAddr(pd
)) {
2916 oldflags
= pp
->pp_IOReq
.iouh_Flags
;
2917 oldnaktimeout
= pp
->pp_IOReq
.iouh_NakTimeout
;
2918 pp
->pp_IOReq
.iouh_Flags
|= UHFF_NAKTIMEOUT
;
2919 pp
->pp_IOReq
.iouh_NakTimeout
= 1000;
2920 pp
->pp_IOReq
.iouh_DevAddr
= 0;
2922 psdPipeSetup(pp
, URTF_IN
|URTF_STANDARD
|URTF_DEVICE
, USR_GET_DESCRIPTOR
, UDT_DEVICE
<<8, 0);
2923 ioerr
= psdDoPipe(pp
, dummybuf
, 8);
2924 if(ioerr
&& (ioerr
!= UHIOERR_RUNTPACKET
)) {
2925 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "GET_DESCRIPTOR (len %ld) failed: %s (%ld)", 8, psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
2926 KPRINTF(15, ("GET_DESCRIPTOR (8) failed %ld!\n", ioerr
));
2929 KPRINTF(1, ("Setting DevAddr %ld...\n", pd
->pd_DevAddr
));
2930 psdPipeSetup(pp
, URTF_STANDARD
|URTF_DEVICE
, USR_SET_ADDRESS
, pd
->pd_DevAddr
, 0);
2931 ioerr
= psdDoPipe(pp
, NULL
, 0);
2933 This is tricky: Maybe the device has accepted the command,
2934 but failed to send an ACK. Now, every resend trial will
2935 go to the wrong address!
2937 if((ioerr
== UHIOERR_TIMEOUT
) || (ioerr
== UHIOERR_STALL
)) {
2938 KPRINTF(1, ("First attempt failed, retrying new address\n"));
2939 /*pp->pp_IOReq.iouh_DevAddr = pd->pd_DevAddr;*/
2941 ioerr
= psdDoPipe(pp
, NULL
, 0);
2942 /*pp->pp_IOReq.iouh_DevAddr = 0;*/
2946 pd
->pd_Flags
|= PDFF_HASDEVADDR
|PDFF_CONNECTED
;
2947 pp
->pp_IOReq
.iouh_DevAddr
= pd
->pd_DevAddr
;
2949 psdDelayMS(50); /* Allowed time to settle */
2951 KPRINTF(1, ("Getting MaxPktSize0...\n"));
2952 psdPipeSetup(pp
, URTF_IN
|URTF_STANDARD
|URTF_DEVICE
, USR_GET_DESCRIPTOR
, UDT_DEVICE
<<8, 0);
2953 ioerr
= psdDoPipe(pp
, &usdd
, 8);
2955 switch(usdd
.bMaxPacketSize0
)
2961 pp
->pp_IOReq
.iouh_MaxPktSize
= pd
->pd_MaxPktSize0
= usdd
.bMaxPacketSize0
;
2963 #ifdef AROS_USB30_CODE
2965 if((AROS_LE2WORD(usdd
.bcdUSB
) >= 0x0300)) {
2966 /* 9 is the only valid value for superspeed mode and it is the exponent of 2 =512 bytes */
2967 pp
->pp_IOReq
.iouh_MaxPktSize
= pd
->pd_MaxPktSize0
= (1<<9);
2972 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
), "Illegal MaxPktSize0=%ld for endpoint 0", (ULONG
) usdd
.bMaxPacketSize0
);
2973 KPRINTF(2, ("Illegal MaxPktSize0=%ld!\n", usdd
.bMaxPacketSize0
));
2974 //pp->pp_IOReq.iouh_MaxPktSize = pd->pd_MaxPktSize0 = 8;
2975 ioerr
= UHIOERR_CRCERROR
;
2982 KPRINTF(1, (" MaxPktSize0 = %ld\n", pd
->pd_MaxPktSize0
));
2983 KPRINTF(1, ("Getting full descriptor...\n"));
2984 ioerr
= psdDoPipe(pp
, &usdd
, sizeof(struct UsbStdDevDesc
));
2987 pAllocDescriptor(pd
, (UBYTE
*) &usdd
);
2988 pd
->pd_Flags
|= PDFF_HASDEVDESC
;
2989 pd
->pd_USBVers
= AROS_WORD2LE(usdd
.bcdUSB
);
2990 pd
->pd_DevClass
= usdd
.bDeviceClass
;
2991 pd
->pd_DevSubClass
= usdd
.bDeviceSubClass
;
2992 pd
->pd_DevProto
= usdd
.bDeviceProtocol
;
2993 pd
->pd_VendorID
= AROS_WORD2LE(usdd
.idVendor
);
2994 pd
->pd_ProductID
= AROS_WORD2LE(usdd
.idProduct
);
2995 pd
->pd_DevVers
= AROS_WORD2LE(usdd
.bcdDevice
);
2996 vendorname
= psdNumToStr(NTS_VENDORID
, (LONG
) pd
->pd_VendorID
, NULL
);
2998 // patch to early determine highspeed roothubs
2999 if((!pd
->pd_Hub
) && (pd
->pd_USBVers
>= 0x200) && (pd
->pd_USBVers
< 0x300)) {
3000 pd
->pd_Flags
|= PDFF_HIGHSPEED
;
3003 #ifdef AROS_USB30_CODE
3004 if(((!pd
->pd_Hub
) && pd
->pd_USBVers
>= 0x300)) {
3005 pd
->pd_Flags
|= PDFF_SUPERSPEED
;
3009 The USB 3.0 and USB 2.0 LPM specifications define a new USB descriptor called the Binary Device Object Store (BOS)
3010 for a USB device, which reports a bcdUSB value greater than 0x0200 in their device descriptor
3012 if((pd
->pd_USBVers
> 0x200)) {
3013 psdPipeSetup(pp
, URTF_IN
|URTF_STANDARD
|URTF_DEVICE
, USR_GET_DESCRIPTOR
, UDT_BOS
<<8, 0);
3014 ioerr_bos
= psdDoPipe(pp
, &usbosd
, sizeof(struct UsbStdBOSDesc
));
3016 XPRINTF(1, ("BOS descriptor received...\n"));
3019 BOS descriptor bLength = sizeof(struct UsbStdBOSDesc)
3020 BOS descriptor bNumDeviceCaps != 0
3021 BOS descriptor wTotalLength >= bLength + (bNumDeviceCaps * sizeof(protocol specific capability descriptor))
3023 if(usbosd
.bLength
!= sizeof(struct UsbStdBOSDesc
)) {
3024 XPRINTF(1, ("Invalid BOS descriptor bLength!\n"));
3027 if(usbosd
.bNumDeviceCaps
== 0) {
3028 XPRINTF(1, ("Invalid BOS descriptor bNumDeviceCaps!\n"));
3029 }else if(usbosd
.wTotalLength
< (usbosd
.bLength
+ (usbosd
.bNumDeviceCaps
* 2))) {
3030 XPRINTF(1, ("Invalid BOS descriptor wTotalLength!\n"));
3034 XPRINTF(1, ("GET_DESCRIPTOR (5) failed %ld!\n", ioerr_bos
));
3039 if(usdd
.iManufacturer
) {
3040 pd
->pd_MnfctrStr
= psdGetStringDescriptor(pp
, usdd
.iManufacturer
);
3044 pd
->pd_ProductStr
= psdGetStringDescriptor(pp
, usdd
.iProduct
);
3047 if(usdd
.iSerialNumber
) {
3048 pd
->pd_SerNumStr
= psdGetStringDescriptor(pp
, usdd
.iSerialNumber
);
3051 if(!pd
->pd_MnfctrStr
) {
3052 pd
->pd_MnfctrStr
= psdCopyStr(vendorname
? vendorname
: (STRPTR
) "n/a");
3055 if(!pd
->pd_ProductStr
) {
3056 hasprodname
= FALSE
;
3057 classname
= psdNumToStr(NTS_CLASSCODE
, (LONG
) pd
->pd_DevClass
, NULL
);
3059 pd
->pd_ProductStr
= psdCopyStrFmt("%s: Vdr=%04lx/PID=%04lx", classname
, pd
->pd_VendorID
, pd
->pd_ProductID
);
3061 pd
->pd_ProductStr
= psdCopyStrFmt("Cls=%ld/Vdr=%04lx/PID=%04lx", pd
->pd_DevClass
, pd
->pd_VendorID
, pd
->pd_ProductID
);
3067 if(!pd
->pd_SerNumStr
) {
3068 pd
->pd_SerNumStr
= psdCopyStr("n/a");
3071 KPRINTF(2, ("Product : %s\n"
3072 "Manufacturer: %s\n"
3073 "SerialNumber: %s\n",
3074 pd
->pd_ProductStr
, pd
->pd_MnfctrStr
, pd
->pd_SerNumStr
));
3075 KPRINTF(2, ("USBVersion: %04lx\n"
3081 "DevVers : %04lx\n",
3082 pd
->pd_USBVers
, pd
->pd_DevClass
, pd
->pd_DevSubClass
, pd
->pd_DevProto
,
3083 pd
->pd_VendorID
, pd
->pd_ProductID
, pd
->pd_DevVers
));
3085 /* check for clones */
3087 while((itpd
= psdGetNextDevice(itpd
)))
3091 if((itpd
->pd_ProductID
== pd
->pd_ProductID
) &&
3092 (itpd
->pd_VendorID
== pd
->pd_VendorID
) &&
3093 (!strcmp(itpd
->pd_SerNumStr
, pd
->pd_SerNumStr
)) &&
3094 (itpd
->pd_CloneCount
== pd
->pd_CloneCount
))
3096 pd
->pd_CloneCount
++;
3102 pd
->pd_IDString
= psdCopyStrFmt("%s-%04lx-%04lx-%s-%02lx", pd
->pd_ProductStr
, pd
->pd_VendorID
, pd
->pd_ProductID
, pd
->pd_SerNumStr
, pd
->pd_CloneCount
);
3104 pStripString(ps
, pd
->pd_MnfctrStr
);
3105 pStripString(ps
, pd
->pd_ProductStr
);
3106 pStripString(ps
, pd
->pd_SerNumStr
);
3108 /* get custom name of device */
3109 pLockSemExcl(ps
, &ps
->ps_ConfigLock
); // Exclusive lock to avoid deadlock situation when promoting read to write
3110 pd
->pd_OldProductStr
= pd
->pd_ProductStr
;
3111 pd
->pd_ProductStr
= NULL
;
3112 haspopupinhibit
= FALSE
;
3113 pic
= psdGetUsbDevCfg("Trident", pd
->pd_IDString
, NULL
);
3116 pd
->pd_IsNewToMe
= FALSE
;
3117 if((pd
->pd_ProductStr
= pGetStringChunk(ps
, pic
, IFFCHNK_NAME
)))
3121 if((chnk
= pFindCfgChunk(ps
, pic
, IFFCHNK_POPUP
)))
3123 struct PsdPoPoCfg
*poc
= (struct PsdPoPoCfg
*) chnk
;
3124 CopyMem(((UBYTE
*) poc
) + 8, ((UBYTE
*) &pd
->pd_PoPoCfg
) + 8, min(AROS_LONG2BE(poc
->poc_Length
), AROS_LONG2BE(pd
->pd_PoPoCfg
.poc_Length
)));
3125 haspopupinhibit
= TRUE
;
3128 pd
->pd_IsNewToMe
= TRUE
;
3129 psdSetUsbDevCfg("Trident", pd
->pd_IDString
, NULL
, NULL
);
3131 if(!pd
->pd_ProductStr
)
3133 pd
->pd_ProductStr
= psdCopyStr(pd
->pd_OldProductStr
);
3135 if(!haspopupinhibit
)
3137 if(pd
->pd_DevClass
== HUB_CLASSCODE
) // hubs default to true
3139 pd
->pd_PoPoCfg
.poc_InhibitPopup
= TRUE
;
3142 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
3144 pd
->pd_NumCfgs
= usdd
.bNumConfigurations
;
3145 KPRINTF(10, ("Device has %ld different configurations\n", pd
->pd_NumCfgs
));
3147 if(pGetDevConfig(pp
))
3150 if(pd
->pd_Configs
.lh_Head
->ln_Succ
)
3152 cfgnum
= ((struct PsdConfig
*) pd
->pd_Configs
.lh_Head
)->pc_CfgNum
;
3154 psdSetDeviceConfig(pp
, cfgnum
); /* *** FIXME *** Workaround for USB2.0 devices */
3158 devclass
= pd
->pd_DevClass
;
3159 pc
= (struct PsdConfig
*) pd
->pd_Configs
.lh_Head
;
3160 while(pc
->pc_Node
.ln_Succ
)
3162 pif
= (struct PsdInterface
*) pc
->pc_Interfaces
.lh_Head
;
3163 while(pif
->pif_Node
.ln_Succ
)
3165 if(pif
->pif_IfClass
)
3169 devclass
= pif
->pif_IfClass
;
3171 if(devclass
!= pif
->pif_IfClass
)
3178 pif
= (struct PsdInterface
*) pif
->pif_Node
.ln_Succ
;
3180 pc
= (struct PsdConfig
*) pc
->pc_Node
.ln_Succ
;
3184 classname
= psdNumToStr(NTS_CLASSCODE
, (LONG
) devclass
, NULL
);
3187 psdFreeVec(pd
->pd_ProductStr
);
3190 pd
->pd_ProductStr
= psdCopyStrFmt("%s (%s/%04lx)",
3191 classname
, vendorname
, pd
->pd_ProductID
);
3193 pd
->pd_ProductStr
= psdCopyStrFmt("%s (%04lx/%04lx)",
3194 classname
, pd
->pd_VendorID
, pd
->pd_ProductID
);
3199 pFixBrokenConfig(pp
);
3200 pp
->pp_IOReq
.iouh_Flags
= oldflags
;
3201 pp
->pp_IOReq
.iouh_NakTimeout
= oldnaktimeout
;
3202 psdUnlockDevice(pd
);
3203 psdCalculatePower(pd
->pd_Hardware
);
3206 KPRINTF(15, ("SetDeviceConfig(1) failed\n"));
3209 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
3210 "Could not acquire device configuration for %s",
3211 pd
->pd_ProductStr
? pd
->pd_ProductStr
: (STRPTR
) "new device");
3212 KPRINTF(15, ("GetDevConfig() failed\n"));
3214 /* Although the device failed to configure fully, maybe
3215 some firmware will able to use this device anyway? */
3216 pp
->pp_IOReq
.iouh_Flags
= oldflags
;
3217 pp
->pp_IOReq
.iouh_NakTimeout
= oldnaktimeout
;
3219 psdUnlockDevice(pd
);
3222 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
3223 "GET_DESCRIPTOR (len %ld) failed: %s (%ld)",
3224 18, psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
3225 KPRINTF(15, ("GET_DESCRIPTOR (18) failed %ld!\n", ioerr
));
3228 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
3229 "GET_DESCRIPTOR (len %ld) failed: %s (%ld)",
3230 8, psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
3231 KPRINTF(15, ("GET_DESCRIPTOR (8) failed %ld!\n", ioerr
));
3234 psdAddErrorMsg(RETURN_FAIL
, (STRPTR
) GM_UNIQUENAME(libname
),
3235 "SET_ADDRESS failed: %s (%ld)",
3236 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
3237 KPRINTF(15, ("SET_ADDRESS failed %ld!\n", ioerr
));
3240 pp
->pp_IOReq
.iouh_Flags
= oldflags
;
3241 pp
->pp_IOReq
.iouh_NakTimeout
= oldnaktimeout
;
3243 psdAddErrorMsg0(RETURN_FAIL
, (STRPTR
) GM_UNIQUENAME(libname
), "This cannot happen! More than 127 devices on the bus???");
3244 KPRINTF(20, ("out of addresses???\n"));
3246 psdAddErrorMsg0(RETURN_FAIL
, (STRPTR
) GM_UNIQUENAME(libname
), "Device enumeration failed, sorry.");
3247 psdUnlockDevice(pd
);
3253 /* /// "psdGetNextDevice()" */
3254 AROS_LH1(struct PsdDevice
*, psdGetNextDevice
,
3255 AROS_LHA(struct PsdDevice
*, pd
, A0
),
3256 LIBBASETYPEPTR
, ps
, 21, psd
)
3259 struct PsdHardware
*phw
;
3261 KPRINTF(1, ("psdGetNextDevice(%p)\n", pd
));
3264 /* Is there another device node in the current hardware? */
3265 if(pd
->pd_Node
.ln_Succ
->ln_Succ
)
3267 return((struct PsdDevice
*) pd
->pd_Node
.ln_Succ
);
3269 /* No, then check if there's another hardware to scan */
3270 phw
= (struct PsdHardware
*) pd
->pd_Hardware
->phw_Node
.ln_Succ
;
3272 /* No context, start with first hardware */
3273 phw
= (struct PsdHardware
*) ps
->ps_Hardware
.lh_Head
;
3275 while(phw
->phw_Node
.ln_Succ
)
3277 pd
= (struct PsdDevice
*) phw
->phw_Devices
.lh_Head
;
3278 /* Is this an valid entry, or is the list empty? */
3279 if(pd
->pd_Node
.ln_Succ
)
3283 phw
= (struct PsdHardware
*) phw
->phw_Node
.ln_Succ
;
3285 /* End of list reached */
3291 /* /// "psdSuspendBindings()" */
3292 AROS_LH1(BOOL
, psdSuspendBindings
,
3293 AROS_LHA(struct PsdDevice
*, pd
, A0
),
3294 LIBBASETYPEPTR
, ps
, 100, psd
)
3297 struct PsdUsbClass
*puc
;
3298 struct PsdConfig
*pc
;
3299 struct PsdInterface
*pif
;
3304 KPRINTF(5, ("psdSuspendBindings(%p)\n", pd
));
3307 if(ps
->ps_GlobalCfg
->pgc_ForceSuspend
&& (pd
->pd_CurrentConfig
->pc_Attr
& USCAF_REMOTE_WAKEUP
))
3311 // ask existing bindings to go to suspend first -- if they don't support it, break off
3312 if(pd
->pd_DevBinding
)
3314 if(pd
->pd_Flags
& PDFF_APPBINDING
)
3318 // can't suspend application binding devices
3319 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
3320 "Cannot suspend with application binding on '%s'.",
3324 psdReleaseDevBinding(pd
);
3326 if((puc
= pd
->pd_ClsBinding
))
3329 usbGetAttrs(UGA_CLASS
, NULL
, UCCA_SupportsSuspend
, &suspendable
, TAG_END
);
3332 res
= usbDoMethod(UCM_AttemptSuspendDevice
, pd
->pd_DevBinding
);
3335 // didn't want to suspend
3336 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
3337 "Class '%s' failed to suspend device '%s'.",
3338 puc
->puc_Node
.ln_Name
, pd
->pd_ProductStr
);
3342 if(pd
->pd_IOBusyCount
)
3346 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
3347 "Class '%s' does not support suspending.",
3348 puc
->puc_Node
.ln_Name
);
3351 psdReleaseDevBinding(pd
);
3354 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
3355 "Class '%s' does not support suspending, but has no active IO. Suspending anyway.",
3356 puc
->puc_Node
.ln_Name
);
3361 pc
= pd
->pd_CurrentConfig
;
3362 pif
= (struct PsdInterface
*) pc
->pc_Interfaces
.lh_Head
;
3363 while(pif
->pif_Node
.ln_Succ
)
3365 if(pif
->pif_IfBinding
)
3367 if((puc
= pif
->pif_ClsBinding
))
3370 usbGetAttrs(UGA_CLASS
, NULL
, UCCA_SupportsSuspend
, &suspendable
, TAG_END
);
3373 res
= usbDoMethod(UCM_AttemptSuspendDevice
, pif
->pif_IfBinding
);
3376 // didn't want to suspend
3377 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
3378 "%s failed to suspend device '%s'.",
3379 puc
->puc_Node
.ln_Name
, pd
->pd_ProductStr
);
3383 if(pd
->pd_IOBusyCount
)
3388 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
3389 "%s does not support suspending.",
3390 puc
->puc_Node
.ln_Name
);
3393 psdReleaseIfBinding(pif
);
3396 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
3397 "%s does not support suspending, but has no active IO. Suspending anyway.",
3398 puc
->puc_Node
.ln_Name
);
3403 pif
= (struct PsdInterface
*) pif
->pif_Node
.ln_Succ
;
3412 /* /// "psdSuspendDevice()" */
3413 AROS_LH1(BOOL
, psdSuspendDevice
,
3414 AROS_LHA(struct PsdDevice
*, pd
, A0
),
3415 LIBBASETYPEPTR
, ps
, 98, psd
)
3418 struct PsdUsbClass
*puc
;
3419 struct PsdDevice
*hubpd
;
3423 KPRINTF(5, ("psdSuspendDevice(%p)\n", pd
));
3426 if(pd
->pd_Flags
& PDFF_SUSPENDED
)
3431 if(!hubpd
) // suspend root hub
3433 // suspend whole USB, using the HCI UHCMD_USBSUSPEND command
3434 // FIXME currently unsupported!
3435 psdAddErrorMsg0(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
), "Suspending of root hub currently not supported.");
3439 psdLockWriteDevice(pd
);
3440 res
= psdSuspendBindings(pd
);
3441 psdUnlockDevice(pd
);
3444 psdLockReadDevice(pd
);
3445 if((binding
= hubpd
->pd_DevBinding
) && (puc
= hubpd
->pd_ClsBinding
))
3447 res
= usbDoMethod(UCM_HubSuspendDevice
, binding
, pd
);
3449 psdUnlockDevice(pd
);
3454 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
3455 "Suspending of device '%s' failed.",
3463 /* /// "psdResumeBindings()" */
3464 AROS_LH1(BOOL
, psdResumeBindings
,
3465 AROS_LHA(struct PsdDevice
*, pd
, A0
),
3466 LIBBASETYPEPTR
, ps
, 101, psd
)
3469 struct PsdUsbClass
*puc
;
3470 struct PsdConfig
*pc
;
3471 struct PsdInterface
*pif
;
3473 BOOL rescan
= FALSE
;
3475 KPRINTF(5, ("psdResumeBindings(%p)\n", pd
));
3478 // ask existing bindings to resume -- if they don't support it, rebind
3479 if(pd
->pd_DevBinding
)
3481 if(!(pd
->pd_Flags
& PDFF_APPBINDING
))
3483 if((puc
= pd
->pd_ClsBinding
))
3485 res
= usbDoMethod(UCM_AttemptResumeDevice
, pd
->pd_DevBinding
);
3488 // if the device couldn't resume, better get rid of the binding
3489 psdReleaseDevBinding(pd
);
3495 pc
= pd
->pd_CurrentConfig
;
3496 pif
= (struct PsdInterface
*) pc
->pc_Interfaces
.lh_Head
;
3497 while(pif
->pif_Node
.ln_Succ
)
3499 if(pif
->pif_IfBinding
)
3501 if((puc
= pif
->pif_ClsBinding
))
3503 res
= usbDoMethod(UCM_AttemptResumeDevice
, pif
->pif_IfBinding
);
3506 // didn't want to suspend
3507 psdReleaseIfBinding(pif
);
3513 pif
= (struct PsdInterface
*) pif
->pif_Node
.ln_Succ
;
3525 /* /// "psdResumeDevice()" */
3526 AROS_LH1(BOOL
, psdResumeDevice
,
3527 AROS_LHA(struct PsdDevice
*, pd
, A0
),
3528 LIBBASETYPEPTR
, ps
, 99, psd
)
3531 struct PsdUsbClass
*puc
;
3532 struct PsdDevice
*hubpd
;
3536 KPRINTF(5, ("psdResumeDevice(%p)\n", pd
));
3539 if(!(pd
->pd_Flags
& PDFF_SUSPENDED
))
3544 if(!hubpd
) // resume root hub
3546 // resume whole USB, using the HCI UHCMD_USBRESUME command
3547 // FIXME currently unsupported!
3550 psdLockWriteDevice(pd
);
3551 if((binding
= hubpd
->pd_DevBinding
) && (puc
= hubpd
->pd_ClsBinding
))
3553 res
= usbDoMethod(UCM_HubResumeDevice
, binding
, pd
);
3555 psdUnlockDevice(pd
);
3559 psdResumeBindings(pd
);
3568 /* /// "psdFindDeviceA()" */
3569 AROS_LH2(struct PsdDevice
*, psdFindDeviceA
,
3570 AROS_LHA(struct PsdDevice
*, pd
, A0
),
3571 AROS_LHA(struct TagItem
*, tags
, A1
),
3572 LIBBASETYPEPTR
, ps
, 44, psd
)
3577 KPRINTF(2, ("psdFindDeviceA(%p, %p)\n", pd
, tags
));
3578 while((pd
= psdGetNextDevice(pd
)))
3581 if((ti
= FindTagItem(DA_ProductID
, tags
)))
3583 if(ti
->ti_Data
!= pd
->pd_ProductID
)
3588 if((ti
= FindTagItem(DA_VendorID
, tags
)))
3590 if(ti
->ti_Data
!= pd
->pd_VendorID
)
3595 if((ti
= FindTagItem(DA_Class
, tags
)))
3597 if(ti
->ti_Data
!= pd
->pd_DevClass
)
3602 if((ti
= FindTagItem(DA_SubClass
, tags
)))
3604 if(ti
->ti_Data
!= pd
->pd_DevSubClass
)
3609 if((ti
= FindTagItem(DA_Protocol
, tags
)))
3611 if(ti
->ti_Data
!= pd
->pd_DevProto
)
3616 if((ti
= FindTagItem(DA_Version
, tags
)))
3618 if(ti
->ti_Data
!= pd
->pd_DevVers
)
3623 if((ti
= FindTagItem(DA_SerialNumber
, tags
)))
3625 if(strcmp((STRPTR
) ti
->ti_Data
, pd
->pd_SerNumStr
))
3630 if((ti
= FindTagItem(DA_ProductName
, tags
)))
3632 if(strcmp((STRPTR
) ti
->ti_Data
, pd
->pd_ProductStr
))
3637 if((ti
= FindTagItem(DA_Manufacturer
, tags
)))
3639 if(strcmp((STRPTR
) ti
->ti_Data
, pd
->pd_MnfctrStr
))
3644 if((ti
= FindTagItem(DA_IDString
, tags
)))
3646 if(strcmp((STRPTR
) ti
->ti_Data
, pd
->pd_IDString
))
3651 if((ti
= FindTagItem(DA_Binding
, tags
)))
3653 if(ti
->ti_Data
!= (IPTR
) pd
->pd_DevBinding
)
3658 if((ti
= FindTagItem(DA_HubDevice
, tags
)))
3660 if(ti
->ti_Data
!= (IPTR
) pd
->pd_Hub
)
3676 /* *** Hardware *** */
3678 /* /// "pFindHardware()" */
3679 struct PsdHardware
* pFindHardware(LIBBASETYPEPTR ps
, STRPTR name
, ULONG unit
)
3681 struct PsdHardware
*phw
;
3685 phw
= (struct PsdHardware
*) ps
->ps_Hardware
.lh_Head
;
3686 while(phw
->phw_Node
.ln_Succ
)
3688 if((phw
->phw_Unit
== unit
) && (!strcmp(phw
->phw_DevName
, name
)))
3693 phw
= (struct PsdHardware
*) phw
->phw_Node
.ln_Succ
;
3697 if((*name
== '/') || (*name
== ':'))
3709 /* /// "psdEnumerateHardware()" */
3710 AROS_LH1(struct PsdDevice
*, psdEnumerateHardware
,
3711 AROS_LHA(struct PsdHardware
*, phw
, A0
),
3712 LIBBASETYPEPTR
, ps
, 14, psd
)
3715 struct PsdDevice
*pd
= NULL
;
3718 KPRINTF(2, ("psdEnumerateHardware(%p)\n", phw
));
3720 if((mp
= CreateMsgPort()))
3723 if((pd
= psdAllocDevice(phw
)))
3726 if((pp
= psdAllocPipe(pd
, mp
, NULL
)))
3728 //pp->pp_IOReq.iouh_Flags |= UHFF_NAKTIMEOUT;
3729 //pp->pp_IOReq.iouh_NakTimeout = 1000;
3730 pd
->pd_Flags
|= PDFF_CONNECTED
;
3731 pp
->pp_IOReq
.iouh_Req
.io_Command
= UHCMD_USBRESET
;
3732 psdDoPipe(pp
, NULL
, 0);
3733 pp
->pp_IOReq
.iouh_Req
.io_Command
= UHCMD_CONTROLXFER
;
3734 psdDelayMS(100); // wait for root hub to settle
3735 if(psdEnumerateDevice(pp
))
3737 KPRINTF(1, ("Enumeration finished!\n"));
3738 psdAddErrorMsg0(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
), "Root hub has been enumerated.");
3741 phw
->phw_RootDevice
= pd
;
3742 psdSendEvent(EHMB_ADDDEVICE
, pd
, NULL
);
3747 pFreeBindings(ps
, pd
);
3748 pFreeDevice(ps
, pd
);
3754 psdAddErrorMsg0(RETURN_FAIL
, (STRPTR
) GM_UNIQUENAME(libname
), "Root hub enumeration failed. Blame your hardware driver programmer.");
3760 /* /// "psdRemHardware()" */
3761 AROS_LH1(void, psdRemHardware
,
3762 AROS_LHA(struct PsdHardware
*, phw
, A0
),
3763 LIBBASETYPEPTR
, ps
, 13, psd
)
3766 struct PsdDevice
*pd
;
3769 KPRINTF(5, ("FreeHardware(%p)\n", phw
));
3771 pd
= (struct PsdDevice
*) phw
->phw_Devices
.lh_Head
;
3772 while(pd
->pd_Node
.ln_Succ
)
3774 pFreeBindings(ps
, pd
);
3775 pFreeDevice(ps
, pd
);
3776 psdSendEvent(EHMB_REMDEVICE
, pd
, NULL
);
3777 pd
= (struct PsdDevice
*) phw
->phw_Devices
.lh_Head
;
3780 pd
= (struct PsdDevice
*) phw
->phw_DeadDevices
.lh_Head
;
3781 while(pd
->pd_Node
.ln_Succ
)
3785 KPRINTF(20, ("Can't remove device, usecnt %ld\n", pd
->pd_UseCnt
));
3788 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
3789 "Can't remove device '%s', there are still %ld pipes in use...",
3790 pd
->pd_ProductStr
, pd
->pd_UseCnt
);
3794 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
3795 "Okay, going down with device '%s' anyway, maybe the driver crashed?",
3803 pFreeDevice(ps
, pd
);
3804 //psdSendEvent(EHMB_REMDEVICE, pd, NULL);
3806 pd
= (struct PsdDevice
*) phw
->phw_DeadDevices
.lh_Head
;
3810 /* Note that the subtask unlinks the hardware! */
3811 phw
->phw_ReadySignal
= SIGB_SINGLE
;
3812 phw
->phw_ReadySigTask
= FindTask(NULL
);
3815 Signal(phw
->phw_Task
, SIGBREAKF_CTRL_C
);
3818 while(phw
->phw_Task
)
3820 Wait(1L<<phw
->phw_ReadySignal
);
3822 //FreeSignal(phw->phw_ReadySignal);
3823 KPRINTF(1, ("FreeHardware(%p) freevec name\n", phw
));
3824 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
3825 "Removed hardware %s/%ld. Bye bye!",
3826 phw
->phw_DevName
, phw
->phw_Unit
);
3827 psdFreeVec(phw
->phw_DevName
);
3828 psdFreeVec(phw
->phw_ProductName
);
3829 psdFreeVec(phw
->phw_Manufacturer
);
3830 psdFreeVec(phw
->phw_Description
);
3831 psdFreeVec(phw
->phw_Copyright
);
3833 psdSendEvent(EHMB_REMHARDWARE
, phw
, NULL
);
3834 KPRINTF(1, ("FreeHardware(%p) done\n", phw
));
3839 /* /// "psdAddHardware()" */
3840 AROS_LH2(struct PsdHardware
*,psdAddHardware
,
3841 AROS_LHA(STRPTR
, name
, A0
),
3842 AROS_LHA(ULONG
, unit
, D0
),
3843 LIBBASETYPEPTR
, ps
, 12, psd
)
3846 struct PsdHardware
*phw
;
3848 struct Task
*tmptask
;
3849 KPRINTF(5, ("psdAddHardware(%s, %ld)\n", name
, unit
));
3851 if((phw
= psdAllocVec(sizeof(struct PsdHardware
))))
3853 NewList(&phw
->phw_Devices
);
3854 NewList(&phw
->phw_DeadDevices
);
3855 phw
->phw_Unit
= unit
;
3857 if((phw
->phw_Node
.ln_Name
= phw
->phw_DevName
= psdCopyStr(name
)))
3859 psdSafeRawDoFmt(buf
, 64, "usbhw<%s/%ld>", name
, unit
);
3860 phw
->phw_ReadySignal
= SIGB_SINGLE
;
3861 phw
->phw_ReadySigTask
= FindTask(NULL
);
3862 SetSignal(0, SIGF_SINGLE
); // clear single bit
3863 if((tmptask
= psdSpawnSubTask(buf
, pDeviceTask
, phw
)))
3865 psdBorrowLocksWait(tmptask
, 1UL<<phw
->phw_ReadySignal
);
3868 phw
->phw_ReadySigTask
= NULL
;
3869 //FreeSignal(phw->phw_ReadySignal);
3870 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
3871 "New hardware %s/%ld added (%s).",
3874 phw
->phw_ProductName
);
3875 psdSendEvent(EHMB_ADDHARDWARE
, phw
, NULL
);
3879 phw
->phw_ReadySigTask
= NULL
;
3880 //FreeSignal(phw->phw_ReadySignal);
3881 psdFreeVec(phw
->phw_DevName
);
3890 /* /// "psdCalculatePower()" */
3891 AROS_LH1(void, psdCalculatePower
,
3892 AROS_LHA(struct PsdHardware
*, phw
, A0
),
3893 LIBBASETYPEPTR
, ps
, 78, psd
)
3896 struct PsdDevice
*roothub
= NULL
;
3897 struct PsdDevice
*pd
;
3901 pd
= (struct PsdDevice
*) phw
->phw_Devices
.lh_Head
;
3902 while(pd
->pd_Node
.ln_Succ
)
3909 pd
= (struct PsdDevice
*) pd
->pd_Node
.ln_Succ
;
3916 roothub
->pd_PowerDrain
= 0;
3917 roothub
->pd_PowerSupply
= 500;
3919 /* calculate drain */
3920 pPowerRecurseDrain(ps
, roothub
);
3922 /* calculate supply */
3923 pPowerRecurseSupply(ps
, roothub
);
3931 /* /// "psdAllocPipe()" */
3932 AROS_LH3(struct PsdPipe
*, psdAllocPipe
,
3933 AROS_LHA(struct PsdDevice
*, pd
, A0
),
3934 AROS_LHA(struct MsgPort
*, mp
, A1
),
3935 AROS_LHA(struct PsdEndpoint
*, pep
, A2
),
3936 LIBBASETYPEPTR
, ps
, 24, psd
)
3940 struct PsdDevice
*hubpd
;
3942 KPRINTF(2, ("psdAllocPipe(%p, %p, %p)\n", pd
, mp
, pep
));
3947 if(pep
&& (pep
->pep_TransType
== USEAF_ISOCHRONOUS
) && (!(pep
->pep_Interface
->pif_Config
->pc_Device
->pd_Hardware
->phw_Capabilities
& UHCF_ISO
)))
3949 psdAddErrorMsg0(RETURN_FAIL
, (STRPTR
) GM_UNIQUENAME(libname
), "Your HW controller driver does not support iso transfers. Sorry.");
3953 if((pp
= psdAllocVec(sizeof(struct PsdPipe
))))
3955 pp
->pp_Msg
.mn_Node
.ln_Type
= NT_FREEMSG
;
3956 pp
->pp_MsgPort
= pp
->pp_Msg
.mn_ReplyPort
= mp
;
3957 pp
->pp_Msg
.mn_Length
= sizeof(struct PsdPipe
);
3959 pp
->pp_Endpoint
= pep
;
3960 pp
->pp_IOReq
= *(pd
->pd_Hardware
->phw_RootIOReq
);
3961 pp
->pp_IOReq
.iouh_DevAddr
= pd
->pd_DevAddr
;
3962 if(pd
->pd_Flags
& PDFF_LOWSPEED
)
3964 pp
->pp_IOReq
.iouh_Flags
|= UHFF_LOWSPEED
;
3966 if(pd
->pd_Flags
& PDFF_HIGHSPEED
)
3968 pp
->pp_IOReq
.iouh_Flags
|= UHFF_HIGHSPEED
;
3971 switch(pep
->pep_NumTransMuFr
)
3974 pp
->pp_IOReq
.iouh_Flags
|= UHFF_MULTI_2
;
3977 pp
->pp_IOReq
.iouh_Flags
|= UHFF_MULTI_3
;
3981 pp
->pp_IOReq
.iouh_Flags
|= UHFF_MULTI_1
;
3984 pp
->pp_IOReq
.iouh_Flags
|= UHFF_MULTI_1
;
3987 #ifdef AROS_USB30_CODE
3988 if(pd
->pd_Flags
& PDFF_SUPERSPEED
)
3990 pp
->pp_IOReq
.iouh_Flags
|= UHFF_SUPERSPEED
;
3993 if(pd
->pd_Flags
& PDFF_NEEDSSPLIT
)
3995 /* USB1.1 device connected to a USB2.0 hub */
3996 pp
->pp_IOReq
.iouh_Flags
|= UHFF_SPLITTRANS
;
3998 pp
->pp_IOReq
.iouh_SplitHubPort
= pd
->pd_HubPort
;
3999 // find the root USB 2.0 hub in the tree
4000 while(hubpd
&& !(hubpd
->pd_Flags
& PDFF_HIGHSPEED
))
4002 pp
->pp_IOReq
.iouh_SplitHubPort
= hubpd
->pd_HubPort
;
4003 hubpd
= hubpd
->pd_Hub
;
4007 psdAddErrorMsg0(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
), "Internal error obtaining split transaction hub!");
4011 pp
->pp_IOReq
.iouh_Flags
|= (hubpd
->pd_HubThinkTime
<<UHFS_THINKTIME
);
4012 pp
->pp_IOReq
.iouh_SplitHubAddr
= hubpd
->pd_DevAddr
;
4016 switch(pep
->pep_TransType
)
4019 pp
->pp_IOReq
.iouh_Req
.io_Command
= UHCMD_CONTROLXFER
;
4021 case USEAF_ISOCHRONOUS
:
4022 pp
->pp_IOReq
.iouh_Req
.io_Command
= UHCMD_ISOXFER
;
4025 pp
->pp_IOReq
.iouh_Req
.io_Command
= UHCMD_BULKXFER
;
4027 case USEAF_INTERRUPT
:
4028 pp
->pp_IOReq
.iouh_Req
.io_Command
= UHCMD_INTXFER
;
4031 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
4032 "AllocPipe(): Illegal transfer type %ld",
4033 pep
->pep_TransType
);
4034 KPRINTF(20, ("Illegal transfer type for endpoint!"));
4039 pp
->pp_IOReq
.iouh_Dir
= (pep
->pep_Direction
? UHDIR_IN
: UHDIR_OUT
);
4040 pp
->pp_IOReq
.iouh_Endpoint
= pep
->pep_EPNum
;
4041 pp
->pp_IOReq
.iouh_MaxPktSize
= pep
->pep_MaxPktSize
;
4042 pp
->pp_IOReq
.iouh_Interval
= pep
->pep_Interval
;
4044 pp
->pp_IOReq
.iouh_Req
.io_Command
= UHCMD_CONTROLXFER
;
4045 pp
->pp_IOReq
.iouh_Dir
= UHDIR_SETUP
;
4046 pp
->pp_IOReq
.iouh_Endpoint
= 0;
4047 pp
->pp_IOReq
.iouh_MaxPktSize
= pd
->pd_MaxPktSize0
;
4057 /* /// "psdFreePipe()" */
4058 AROS_LH1(void, psdFreePipe
,
4059 AROS_LHA(struct PsdPipe
*, pp
, A1
),
4060 LIBBASETYPEPTR
, ps
, 25, psd
)
4063 struct PsdDevice
*pd
;
4068 KPRINTF(2, ("psdFreePipe(%p)\n", pp
));
4071 if(pp
->pp_Msg
.mn_Node
.ln_Type
== NT_MESSAGE
)
4073 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
4074 "Tried to free pipe on %s that was still pending!", pd
->pd_ProductStr
);
4079 if(!(--pd
->pd_UseCnt
) && (pd
->pd_Flags
& PDFF_DELEXPUNGE
))
4081 KPRINTF(20, ("Finally getting rid of device %s\n", pd
->pd_ProductStr
));
4082 pFreeDevice(ps
, pd
);
4083 //psdSendEvent(EHMB_REMDEVICE, pd, NULL);
4091 /* /// "psdPipeSetup()" */
4092 AROS_LH5(void, psdPipeSetup
,
4093 AROS_LHA(struct PsdPipe
*, pp
, A1
),
4094 AROS_LHA(UWORD
, rt
, D0
),
4095 AROS_LHA(UWORD
, rq
, D1
),
4096 AROS_LHA(UWORD
, val
, D2
),
4097 AROS_LHA(UWORD
, idx
, D3
),
4098 LIBBASETYPEPTR
, ps
, 26, psd
)
4101 struct UsbSetupData
*usd
= &pp
->pp_IOReq
.iouh_SetupData
;
4103 KPRINTF(1, ("psdSetupPipe(%p, (%02lx %02lx %04lx %04lx))\n",
4104 pp
, rt
, rq
, val
, idx
));
4105 usd
->bmRequestType
= rt
;
4107 usd
->wValue
= AROS_WORD2LE(val
);
4108 usd
->wIndex
= AROS_WORD2LE(idx
);
4113 /* /// "psdDoPipe()" */
4114 AROS_LH3(LONG
, psdDoPipe
,
4115 AROS_LHA(struct PsdPipe
*, pp
, A1
),
4116 AROS_LHA(APTR
, data
, A0
),
4117 AROS_LHA(ULONG
, len
, D0
),
4118 LIBBASETYPEPTR
, ps
, 27, psd
)
4121 struct PsdDevice
*pd
= pp
->pp_Device
;
4122 KPRINTF(200, ("psdDoPipe(%p, %p, %ld)\n", pp
, data
, len
));
4124 if(pd
->pd_Flags
& PDFF_CONNECTED
)
4126 if(pd
->pd_Flags
& PDFF_SUSPENDED
)
4128 // make sure the device is up and running before trying to send a new pipe
4129 psdResumeDevice(pd
);
4132 pp
->pp_IOReq
.iouh_Data
= data
;
4133 pp
->pp_IOReq
.iouh_Length
= len
;
4134 if(!pp
->pp_Endpoint
)
4136 pp
->pp_IOReq
.iouh_SetupData
.wLength
= AROS_WORD2LE(len
);
4138 PutMsg(&pd
->pd_Hardware
->phw_TaskMsgPort
, &pp
->pp_Msg
);
4139 ++pd
->pd_IOBusyCount
;
4140 GetSysTime((APTR
) &pd
->pd_LastActivity
);
4141 return(psdWaitPipe(pp
));
4144 pp
->pp_IOReq
.iouh_Actual
= 0;
4145 pp
->pp_Msg
.mn_Node
.ln_Type
= NT_FREEMSG
;
4146 return(pp
->pp_IOReq
.iouh_Req
.io_Error
= UHIOERR_TIMEOUT
);
4152 /* /// "psdSendPipe()" */
4153 AROS_LH3(void, psdSendPipe
,
4154 AROS_LHA(struct PsdPipe
*, pp
, A1
),
4155 AROS_LHA(APTR
, data
, A0
),
4156 AROS_LHA(ULONG
, len
, D0
),
4157 LIBBASETYPEPTR
, ps
, 28, psd
)
4160 struct PsdDevice
*pd
= pp
->pp_Device
;
4161 KPRINTF(200, ("psdSendPipe(%p, %p, %ld)\n", pp
, data
, len
));
4162 if(pd
->pd_Flags
& PDFF_CONNECTED
)
4164 if(pd
->pd_Flags
& PDFF_SUSPENDED
)
4166 // make sure the device is up and running before trying to send a new pipe
4167 psdResumeDevice(pd
);
4170 pp
->pp_IOReq
.iouh_Data
= data
;
4171 pp
->pp_IOReq
.iouh_Length
= len
;
4172 if(!pp
->pp_Endpoint
)
4174 pp
->pp_IOReq
.iouh_SetupData
.wLength
= AROS_WORD2LE(len
);
4176 PutMsg(&pd
->pd_Hardware
->phw_TaskMsgPort
, &pp
->pp_Msg
);
4177 GetSysTime((APTR
) &pd
->pd_LastActivity
);
4178 ++pd
->pd_IOBusyCount
;
4181 pp
->pp_IOReq
.iouh_Actual
= 0;
4182 //pp->pp_Msg.mn_Node.ln_Type = NT_REPLYMSG;
4183 pp
->pp_IOReq
.iouh_Req
.io_Error
= UHIOERR_TIMEOUT
;
4184 ReplyMsg(&pp
->pp_Msg
);
4185 ++pd
->pd_IOBusyCount
;
4191 /* /// "psdAbortPipe()" */
4192 AROS_LH1(void, psdAbortPipe
,
4193 AROS_LHA(struct PsdPipe
*, pp
, A1
),
4194 LIBBASETYPEPTR
, ps
, 29, psd
)
4197 struct PsdPipe
*npp
;
4199 KPRINTF(5, ("psdAbortPipe(%p)\n", pp
));
4200 if(pp
->pp_Msg
.mn_Node
.ln_Type
!= NT_MESSAGE
)
4202 KPRINTF(5, ("Nothing to abort %02lx\n", pp
->pp_IOReq
.iouh_Req
.io_Message
.mn_Node
.ln_Type
));
4205 if((npp
= psdAllocVec(sizeof(struct PsdPipe
))))
4207 //npp->pp_Msg.mn_Node.ln_Type = NT_MESSAGE;
4208 npp
->pp_Device
= pp
->pp_Device
;
4209 npp
->pp_MsgPort
= npp
->pp_Msg
.mn_ReplyPort
= pp
->pp_MsgPort
;
4210 npp
->pp_Msg
.mn_Length
= sizeof(struct PsdPipe
);
4212 npp
->pp_AbortPipe
= pp
;
4213 PutMsg(&pp
->pp_Device
->pd_Hardware
->phw_TaskMsgPort
, &npp
->pp_Msg
);
4221 /* /// "psdWaitPipe()" */
4222 AROS_LH1(LONG
, psdWaitPipe
,
4223 AROS_LHA(struct PsdPipe
*, pp
, A1
),
4224 LIBBASETYPEPTR
, ps
, 30, psd
)
4228 struct PsdDevice
*pd
= pp
->pp_Device
;
4230 KPRINTF(5, ("psdWaitPipe(%p)\n", pp
));
4231 while(pp
->pp_Msg
.mn_Node
.ln_Type
== NT_MESSAGE
)
4233 KPRINTF(5, ("ln_Type = %02lx\n", pp
->pp_Msg
.mn_Node
.ln_Type
));
4234 sigs
|= Wait(1L<<pp
->pp_MsgPort
->mp_SigBit
);
4235 KPRINTF(5, ("sigs = %p\n", sigs
));
4239 if(pp
->pp_Msg
.mn_Node
.ln_Type
== NT_REPLYMSG
)
4241 pp
->pp_Msg
.mn_Node
.ln_Type
= NT_FREEMSG
;
4242 Remove(&pp
->pp_Msg
.mn_Node
);
4244 //if(pp->pp_MsgPort->mp_MsgList.lh_Head->ln_Succ)
4246 // avoid signals getting lost for other messages arriving.
4247 SetSignal(sigs
, sigs
);
4252 Remove(&pp
->pp_Msg
.mn_Node
);
4255 ioerr
= pp
->pp_IOReq
.iouh_Req
.io_Error
;
4258 case UHIOERR_TIMEOUT
:
4261 case UHIOERR_NAKTIMEOUT
:
4263 case UHIOERR_CRCERROR
:
4266 case UHIOERR_RUNTPACKET
:
4268 if(pd
->pd_DeadCount
)
4270 pd
->pd_DeadCount
>>= 1;
4271 /*psdAddErrorMsg(RETURN_OK, (STRPTR) GM_UNIQUENAME(libname),
4272 "Device %s starts recovering with %s (%ld)!",
4274 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);*/
4277 KPRINTF(200, ("psdWaitPipe(%p)=%ld\n", pp
, ioerr
));
4278 --pd
->pd_IOBusyCount
;
4279 GetSysTime((APTR
) &pd
->pd_LastActivity
);
4281 if((pd
->pd_DeadCount
> 19) || ((pd
->pd_DeadCount
> 14) && (pd
->pd_Flags
& (PDFF_HASDEVADDR
|PDFF_HASDEVDESC
))))
4283 if(!(pd
->pd_Flags
& PDFF_DEAD
))
4285 pd
->pd_Flags
|= PDFF_DEAD
;
4286 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
4287 "Device %s probably dropped dead!", pd
->pd_ProductStr
);
4289 psdSendEvent(EHMB_DEVICEDEAD
, pp
->pp_Device
, NULL
);
4292 if((!pd
->pd_DeadCount
) && ((pd
->pd_Flags
& (PDFF_DEAD
|PDFF_CONNECTED
)) == (PDFF_DEAD
|PDFF_CONNECTED
)))
4294 pd
->pd_Flags
&= ~PDFF_DEAD
;
4295 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
4296 "Uuuhuuuhh, the zombie %s returned from the dead!", pd
->pd_ProductStr
);
4304 /* /// "psdCheckPipe()" */
4305 AROS_LH1(struct PsdPipe
*, psdCheckPipe
,
4306 AROS_LHA(struct PsdPipe
*, pp
, A1
),
4307 LIBBASETYPEPTR
, ps
, 71, psd
)
4310 KPRINTF(5, ("psdCheckPipe(%p)\n", pp
));
4311 if(pp
->pp_Msg
.mn_Node
.ln_Type
== NT_MESSAGE
)
4320 /* /// "psdGetPipeActual()" */
4321 AROS_LH1(ULONG
, psdGetPipeActual
,
4322 AROS_LHA(struct PsdPipe
*, pp
, A1
),
4323 LIBBASETYPEPTR
, ps
, 31, psd
)
4326 KPRINTF(1, ("psdGetPipeActual(%p)\n", pp
));
4327 return(pp
->pp_IOReq
.iouh_Actual
);
4332 /* /// "psdGetPipeError()" */
4333 AROS_LH1(LONG
, psdGetPipeError
,
4334 AROS_LHA(struct PsdPipe
*, pp
, A1
),
4335 LIBBASETYPEPTR
, ps
, 32, psd
)
4338 KPRINTF(1, ("psdGetPipeError(%p)\n", pp
));
4339 return((LONG
) pp
->pp_IOReq
.iouh_Req
.io_Error
);
4344 /* *** Streams *** */
4346 /* /// "psdOpenStreamA()" */
4347 AROS_LH2(struct PsdPipeStream
*, psdOpenStreamA
,
4348 AROS_LHA(struct PsdEndpoint
*, pep
, A0
),
4349 AROS_LHA(struct TagItem
*, tags
, A1
),
4350 LIBBASETYPEPTR
, ps
, 72, psd
)
4353 struct PsdPipeStream
*pps
;
4355 KPRINTF(2, ("psdOpenStream(%p, %p)\n", pep
, tags
));
4360 if((pps
= psdAllocVec(sizeof(struct PsdPipeStream
))))
4362 pps
->pps_Device
= pep
->pep_Interface
->pif_Config
->pc_Device
;
4363 pps
->pps_Endpoint
= pep
;
4364 NewList(&pps
->pps_FreePipes
);
4365 NewList(&pps
->pps_ReadyPipes
);
4366 InitSemaphore(&pps
->pps_AccessLock
);
4367 pps
->pps_NakTimeoutTime
= 5000;
4368 if(pep
->pep_Direction
)
4370 /* Defaults for IN */
4371 pps
->pps_NumPipes
= 4;
4372 pps
->pps_Flags
= PSFF_READAHEAD
|PSFF_BUFFERREAD
|PSFF_ALLOWRUNT
;
4373 pps
->pps_BufferSize
= 32*pps
->pps_Endpoint
->pep_MaxPktSize
;
4375 /* Defaults for OUT */
4376 pps
->pps_NumPipes
= 4;
4377 pps
->pps_Flags
= PSFF_NOSHORTPKT
;
4378 pps
->pps_BufferSize
= 4*pps
->pps_Endpoint
->pep_MaxPktSize
;
4381 psdSetAttrsA(PGA_PIPESTREAM
, pps
, tags
);
4384 psdCloseStream(pps
);
4394 /* /// "psdCloseStream()" */
4395 AROS_LH1(void, psdCloseStream
,
4396 AROS_LHA(struct PsdPipeStream
*, pps
, A1
),
4397 LIBBASETYPEPTR
, ps
, 73, psd
)
4403 KPRINTF(2, ("psdCloseStream(%p)\n", pps
));
4408 psdStreamFlush(pps
);
4409 ObtainSemaphore(&pps
->pps_AccessLock
);
4412 for(cnt
= 0; cnt
< pps
->pps_NumPipes
; cnt
++)
4414 pp
= pps
->pps_Pipes
[cnt
];
4415 //if(pp->pp_IOReq.iouh_Req.io_Message.mn_Node.ln_Type == NT_MESSAGE)
4417 KPRINTF(1, ("Abort %ld\n", cnt
));
4419 KPRINTF(1, ("Wait %ld\n", cnt
));
4422 KPRINTF(1, ("Free %ld\n", cnt
));
4425 psdFreeVec(pps
->pps_Pipes
);
4426 if((pps
->pps_Flags
& PSFF_OWNMSGPORT
) && pps
->pps_MsgPort
)
4428 DeleteMsgPort(pps
->pps_MsgPort
);
4431 psdFreeVec(pps
->pps_Buffer
);
4432 ReleaseSemaphore(&pps
->pps_AccessLock
);
4438 /* /// "psdStreamRead()" */
4439 AROS_LH3(LONG
, psdStreamRead
,
4440 AROS_LHA(struct PsdPipeStream
*, pps
, A1
),
4441 AROS_LHA(UBYTE
*, buffer
, A0
),
4442 AROS_LHA(LONG
, length
, D0
),
4443 LIBBASETYPEPTR
, ps
, 74, psd
)
4460 KPRINTF(2, ("psdStreamRead(%p, %p, %ld)\n", pps
, buffer
, length
));
4465 ObtainSemaphore(&pps
->pps_AccessLock
);
4466 KPRINTF(2, ("Sema\n"));
4468 if((!pps
->pps_Pipes
) || (!pps
->pps_Endpoint
->pep_Direction
))
4470 KPRINTF(2, ("Wrong direction!\n"));
4471 pps
->pps_Error
= UHIOERR_BADPARAMS
;
4472 ReleaseSemaphore(&pps
->pps_AccessLock
);
4475 if(!(pps
->pps_Flags
& PSFF_ASYNCIO
))
4477 if(pps
->pps_Flags
& PSFF_BUFFERREAD
)
4479 /* buffered reading */
4482 /* check for incoming packets */
4483 while((pp
= (struct PsdPipe
*) GetMsg(pps
->pps_MsgPort
)))
4485 KPRINTF(1, ("PktBack(%p, %p, %ld/%ld)=%ld\n",
4486 pp
, pp
->pp_IOReq
.iouh_Data
, pp
->pp_IOReq
.iouh_Actual
,
4487 pp
->pp_IOReq
.iouh_Length
, pp
->pp_IOReq
.iouh_Req
.io_Error
));
4489 pps
->pps_ReqBytes
-= pp
->pp_IOReq
.iouh_Length
;
4490 ioerr
= pp
->pp_IOReq
.iouh_Req
.io_Error
;
4491 if((ioerr
== UHIOERR_NAKTIMEOUT
) && pp
->pp_IOReq
.iouh_Actual
)
4498 pps
->pps_Error
= ioerr
;
4500 if(ioerr
!= UHIOERR_TIMEOUT
)
4502 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) "StreamRead",
4503 "Packet(%s) failed: %s (%ld)", (STRPTR
) "b",
4504 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
4506 /* stop automatic queueing */
4507 pps
->pps_Flags
&= ~PSFF_READAHEAD
;
4508 AddTail(&pps
->pps_FreePipes
, &pp
->pp_Msg
.mn_Node
);
4510 /* successfully received packet */
4511 pps
->pps_BytesPending
+= pp
->pp_IOReq
.iouh_Actual
;
4512 AddTail(&pps
->pps_ReadyPipes
, &pp
->pp_Msg
.mn_Node
);
4515 if(length
== -1) /* get all that's there (STRONGLY DISCOURAGED! Might cause buffer overflows) */
4517 length
= pps
->pps_BytesPending
;
4519 /* check for buffered data */
4520 while(length
&& pps
->pps_BytesPending
)
4522 pp
= (struct PsdPipe
*) pps
->pps_ReadyPipes
.lh_Head
;
4523 if(!pp
->pp_Msg
.mn_Node
.ln_Succ
) /* debug */
4525 psdAddErrorMsg0(RETURN_FAIL
, (STRPTR
) "StreamRead", "Readqueue empty!");
4526 ReleaseSemaphore(&pps
->pps_AccessLock
);
4529 if(pp
->pp_IOReq
.iouh_Actual
< pps
->pps_Offset
)
4531 psdAddErrorMsg(RETURN_FAIL
, (STRPTR
) "StreamRead",
4532 "Actual %ld < offset %ld!", pp
->pp_IOReq
.iouh_Actual
, pps
->pps_Offset
);
4533 ReleaseSemaphore(&pps
->pps_AccessLock
);
4536 remlen
= pp
->pp_IOReq
.iouh_Actual
- pps
->pps_Offset
;
4539 KPRINTF(1, ("PktBit(%p, %p, %ld)\n", pp
, buffer
, length
));
4542 KPRINTF(1, ("PktRem(%p, %p, %ld)\n", pp
, buffer
, remlen
));
4545 if(pp
->pp_Flags
& PFF_INPLACE
)
4547 KPRINTF(1, ("PktRemIP(%p, %p, %ld)\n", pp
, buffer
, remlen
));
4549 if(pps
->pps_TermArray
)
4552 KPRINTF(1, ("PktCpyEOF(%p, %p, %ld)\n", pp
, buffer
, remlen
));
4554 srcptr
= &(((UBYTE
*) pp
->pp_IOReq
.iouh_Data
)[pps
->pps_Offset
]);
4555 tarrptr
= pps
->pps_TermArray
;
4562 cchar
= *bufptr
++ = *srcptr
++;
4567 if(cchar
< tarrptr
[tcnt
])
4571 else if(cchar
== tarrptr
[tcnt
])
4575 KPRINTF(2, ("EOF char %02lx found, length = %ld\n", cchar
, remlen
));
4580 if(tarrptr
[tcnt
] == tarrptr
[tcnt
+1])
4585 } while(++tcnt
< 8);
4589 KPRINTF(1, ("PktCpy(%p, %p, %ld)\n", pp
, buffer
, remlen
));
4590 /* quick non-eof mode */
4591 CopyMem(&(((UBYTE
*) pp
->pp_IOReq
.iouh_Data
)[pps
->pps_Offset
]), buffer
, remlen
);
4597 pps
->pps_BytesPending
-= remlen
;
4598 pps
->pps_Offset
+= remlen
;
4599 /* end of packet reached? */
4600 if(pps
->pps_Offset
== pp
->pp_IOReq
.iouh_Actual
)
4602 pps
->pps_Offset
= 0;
4603 Remove(&pp
->pp_Msg
.mn_Node
);
4604 AddTail(&pps
->pps_FreePipes
, &pp
->pp_Msg
.mn_Node
);
4605 /* check for short packet */
4606 if((pps
->pps_Flags
& PSFF_SHORTTERM
) && (pp
->pp_IOReq
.iouh_Actual
% pp
->pp_IOReq
.iouh_MaxPktSize
))
4616 /* start sending out requests */
4618 pp
= (struct PsdPipe
*) pps
->pps_FreePipes
.lh_Head
;
4619 if(!(pps
->pps_BytesPending
|| pps
->pps_ReqBytes
|| pps
->pps_TermArray
|| (length
< pps
->pps_BufferSize
)))
4621 /* faster non-buffered mode */
4622 if(pp
->pp_Msg
.mn_Node
.ln_Succ
)
4624 pp
->pp_Flags
|= PFF_INPLACE
;
4625 Remove(&pp
->pp_Msg
.mn_Node
);
4626 remlen
= length
- (length
% pp
->pp_IOReq
.iouh_MaxPktSize
);
4627 KPRINTF(1, ("OutFast(%p, %p, %ld/%ld)\n",
4628 pp
, buffer
, remlen
, length
));
4629 psdSendPipe(pp
, buffer
, remlen
);
4630 pps
->pps_ReqBytes
+= remlen
;
4631 pp
= (struct PsdPipe
*) pps
->pps_FreePipes
.lh_Head
;
4634 /* slower buffered mode */
4635 while(pp
->pp_Msg
.mn_Node
.ln_Succ
&& ((remlen
> pps
->pps_ReqBytes
) || (pps
->pps_Flags
& PSFF_READAHEAD
)))
4637 pp
->pp_Flags
&= ~PFF_INPLACE
;
4638 Remove(&pp
->pp_Msg
.mn_Node
);
4639 if((pps
->pps_Flags
& PSFF_READAHEAD
) || (remlen
% pp
->pp_IOReq
.iouh_MaxPktSize
))
4641 KPRINTF(1, ("OutSlow(%p, %p, %ld)\n",
4642 pp
, &pps
->pps_Buffer
[pp
->pp_Num
* pps
->pps_BufferSize
], pps
->pps_BufferSize
));
4643 remlen
= pps
->pps_BufferSize
;
4645 KPRINTF(1, ("OutExact(%p, %p, %ld)\n",
4646 pp
, &pps
->pps_Buffer
[pp
->pp_Num
* pps
->pps_BufferSize
], remlen
));
4648 psdSendPipe(pp
, &pps
->pps_Buffer
[pp
->pp_Num
* pps
->pps_BufferSize
], remlen
);
4649 pps
->pps_ReqBytes
+= remlen
;
4650 pp
= (struct PsdPipe
*) pps
->pps_FreePipes
.lh_Head
;
4652 if((!length
) || (pps
->pps_Flags
& PSFF_DONOTWAIT
))
4658 sigmask
= (1UL<<pps
->pps_MsgPort
->mp_SigBit
)|pps
->pps_AbortSigMask
;
4659 KPRINTF(1, ("WaitPort (%p)\n", sigmask
));
4660 sigmask
= Wait(sigmask
);
4661 KPRINTF(1, ("Wait back (%p)\n", sigmask
));
4662 if(sigmask
& pps
->pps_AbortSigMask
)
4664 KPRINTF(1, ("Aborted!\n"));
4666 Signal(FindTask(NULL
), pps
->pps_AbortSigMask
& sigmask
);
4671 /* plain reading (might lose data) */
4672 if(pps
->pps_TermArray
|| (pps
->pps_Flags
& PSFF_READAHEAD
))
4674 psdAddErrorMsg0(RETURN_WARN
, (STRPTR
) "StreamRead", "This mode combination for the stream is not supported!");
4676 /* start sending out requests */
4677 pp
= (struct PsdPipe
*) pps
->pps_FreePipes
.lh_Head
;
4678 if(pp
->pp_Msg
.mn_Node
.ln_Succ
&& length
)
4680 ioerr
= psdDoPipe(pp
, buffer
, length
);
4683 pps
->pps_Error
= ioerr
;
4684 if(ioerr
!= UHIOERR_TIMEOUT
)
4686 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) "StreamRead",
4687 "Packet(%s) failed: %s (%ld)", (STRPTR
) "u",
4688 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
4691 actual
= pp
->pp_IOReq
.iouh_Actual
;
4695 ReleaseSemaphore(&pps
->pps_AccessLock
);
4701 /* /// "psdStreamWrite()" */
4702 AROS_LH3(LONG
, psdStreamWrite
,
4703 AROS_LHA(struct PsdPipeStream
*, pps
, A1
),
4704 AROS_LHA(UBYTE
*, buffer
, A0
),
4705 AROS_LHA(LONG
, length
, D0
),
4706 LIBBASETYPEPTR
, ps
, 75, psd
)
4710 struct PsdPipe
*newpp
;
4723 KPRINTF(2, ("psdStreamWrite(%p, %p, %ld)\n", pps
, buffer
, length
));
4728 ObtainSemaphore(&pps
->pps_AccessLock
);
4730 if((!pps
->pps_Pipes
) || pps
->pps_Endpoint
->pep_Direction
)
4732 KPRINTF(2, ("Wrong direction!\n"));
4733 pps
->pps_Error
= UHIOERR_BADPARAMS
;
4734 ReleaseSemaphore(&pps
->pps_AccessLock
);
4737 if(length
== -1) /* null terminated string mode */
4739 KPRINTF(2, ("EOL mode!\n"));
4740 length
= strlen(buffer
);
4742 if((tarrptr
= pps
->pps_TermArray
)) /* EOF Mode */
4744 KPRINTF(1, ("EOFSearch(%p, %ld)\n", buffer
, length
));
4757 if(cchar
< tarrptr
[tcnt
])
4761 else if(cchar
== tarrptr
[tcnt
])
4764 KPRINTF(2, ("EOF char %02lx found, length = %ld\n", cchar
, length
));
4769 if(tarrptr
[tcnt
] == tarrptr
[tcnt
+1])
4774 } while(++tcnt
< 8);
4778 if(!(pps
->pps_Flags
& PSFF_ASYNCIO
))
4780 pp
= (struct PsdPipe
*) pps
->pps_FreePipes
.lh_Head
;
4781 if(pp
->pp_Msg
.mn_Node
.ln_Succ
&& length
)
4783 if(pps
->pps_Flags
& PSFF_BUFFERWRITE
)
4785 /* buffered writing */
4786 if(pps
->pps_BytesPending
)
4788 remlen
= pps
->pps_BytesPending
% pp
->pp_IOReq
.iouh_MaxPktSize
;
4789 /* align to packet boundary */
4790 if(remlen
+ length
>= pp
->pp_IOReq
.iouh_MaxPktSize
)
4792 /* new data crosses at least on packet size */
4793 if(pps
->pps_BytesPending
+ length
<= pps
->pps_BufferSize
)
4795 /* copy everything up to the last (!) boundary */
4796 remlen
= pps
->pps_BytesPending
+ length
;
4797 remlen
= remlen
- (remlen
% pp
->pp_IOReq
.iouh_MaxPktSize
);
4798 remlen
-= pps
->pps_BytesPending
;
4799 KPRINTF(1, ("PendOptCpy(%p, %ld+%ld/%ld)\n", buffer
, pps
->pps_BytesPending
, remlen
, length
));
4801 /* just calculate amount to copy to the next boundary */
4802 remlen
= pp
->pp_IOReq
.iouh_MaxPktSize
- remlen
;
4803 KPRINTF(1, ("PendOneCpy(%p, %ld+%ld/%ld)\n", buffer
, pps
->pps_BytesPending
, remlen
, length
));
4805 CopyMem(buffer
, &pps
->pps_Buffer
[pps
->pps_BytesPending
], remlen
);
4806 pps
->pps_BytesPending
+= remlen
;
4811 KPRINTF(1, ("PendAdd(%p, %ld+%ld)\n", buffer
, pps
->pps_BytesPending
, length
));
4812 /* only a few bytes, see if we can fit them */
4813 CopyMem(buffer
, &pps
->pps_Buffer
[pps
->pps_BytesPending
], length
);
4814 pps
->pps_BytesPending
+= length
;
4816 //buffer += length; /* not needed */
4819 /* flush some buffers */
4820 if((length
>= pp
->pp_IOReq
.iouh_MaxPktSize
) ||
4821 ((pps
->pps_BytesPending
>= (pps
->pps_BufferSize
>>1)) && (pps
->pps_BytesPending
>= pp
->pp_IOReq
.iouh_MaxPktSize
)))
4823 remlen
= pps
->pps_BytesPending
- (pps
->pps_BytesPending
% pp
->pp_IOReq
.iouh_MaxPktSize
);
4824 KPRINTF(1, ("PendFlush(%ld/%ld)\n", remlen
, pps
->pps_BytesPending
));
4825 Remove(&pp
->pp_Msg
.mn_Node
);
4826 psdSendPipe(pp
, pps
->pps_Buffer
, remlen
);
4827 pps
->pps_ActivePipe
= pp
;
4828 while(!(newpp
= (struct PsdPipe
*) GetMsg(pps
->pps_MsgPort
)))
4830 sigmask
= (1UL<<pps
->pps_MsgPort
->mp_SigBit
)|pps
->pps_AbortSigMask
;
4831 sigmask
= Wait(sigmask
);
4832 if(sigmask
& pps
->pps_AbortSigMask
)
4834 KPRINTF(1, ("Kill signal detected!\n"));
4835 Signal(FindTask(NULL
), pps
->pps_AbortSigMask
& sigmask
);
4843 ioerr
= psdWaitPipe(pp
);
4844 pps
->pps_ActivePipe
= NULL
;
4845 AddTail(&pps
->pps_FreePipes
, &pp
->pp_Msg
.mn_Node
);
4847 /* move end of buffer */
4848 cnt
= pps
->pps_BytesPending
;
4849 tcnt
= pp
->pp_IOReq
.iouh_Actual
;
4850 pps
->pps_BytesPending
-= tcnt
;
4851 bufptr
= pps
->pps_Buffer
;
4852 srcptr
= bufptr
+ tcnt
;
4858 *bufptr
++ = *srcptr
++;
4863 pps
->pps_Error
= ioerr
;
4864 if(ioerr
!= UHIOERR_TIMEOUT
)
4866 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) "StreamWrite",
4867 "Packet(%s) failed: %s (%ld)", (STRPTR
) "b",
4868 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
4870 ReleaseSemaphore(&pps
->pps_AccessLock
);
4875 /* send out large chunk (avoid copying) */
4876 if(length
>= pp
->pp_IOReq
.iouh_MaxPktSize
)
4878 remlen
= length
- (length
% pp
->pp_IOReq
.iouh_MaxPktSize
);
4879 KPRINTF(1, ("BulkFlush(%p, %ld/%ld)\n", buffer
, remlen
, length
));
4880 Remove(&pp
->pp_Msg
.mn_Node
);
4881 psdSendPipe(pp
, buffer
, remlen
);
4882 pps
->pps_ActivePipe
= pp
;
4883 while(!(newpp
= (struct PsdPipe
*) GetMsg(pps
->pps_MsgPort
)))
4885 sigmask
= (1UL<<pps
->pps_MsgPort
->mp_SigBit
)|pps
->pps_AbortSigMask
;
4886 sigmask
= Wait(sigmask
);
4887 if(sigmask
& pps
->pps_AbortSigMask
)
4889 KPRINTF(1, ("Kill signal detected!\n"));
4890 Signal(FindTask(NULL
), pps
->pps_AbortSigMask
& sigmask
);
4898 ioerr
= psdWaitPipe(pp
);
4899 pps
->pps_ActivePipe
= NULL
;
4900 AddTail(&pps
->pps_FreePipes
, &pp
->pp_Msg
.mn_Node
);
4902 actual
+= pp
->pp_IOReq
.iouh_Actual
;
4903 buffer
+= pp
->pp_IOReq
.iouh_Actual
;
4904 length
-= pp
->pp_IOReq
.iouh_Actual
;
4907 pps
->pps_Error
= ioerr
;
4908 if(ioerr
!= UHIOERR_TIMEOUT
)
4910 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) "StreamWrite",
4911 "Packet(%s) failed: %s (%ld)", (STRPTR
) "c",
4912 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
4914 ReleaseSemaphore(&pps
->pps_AccessLock
);
4918 /* buffer remaining bytes */
4921 KPRINTF(1, ("BufAdd(%p, %ld)\n", buffer
, length
));
4922 /* only a few bytes left, so lets buffer them */
4923 CopyMem(buffer
, &pps
->pps_Buffer
[pps
->pps_BytesPending
], length
);
4924 pps
->pps_BytesPending
+= length
;
4929 /* start sending out requests */
4930 KPRINTF(1, ("PlainWrite(%p, %ld)\n", buffer
, length
));
4931 Remove(&pp
->pp_Msg
.mn_Node
);
4932 psdSendPipe(pp
, buffer
, length
);
4933 pps
->pps_ActivePipe
= pp
;
4934 while(!(newpp
= (struct PsdPipe
*) GetMsg(pps
->pps_MsgPort
)))
4936 sigmask
= (1UL<<pps
->pps_MsgPort
->mp_SigBit
)|pps
->pps_AbortSigMask
;
4937 sigmask
= Wait(sigmask
);
4938 if(sigmask
& pps
->pps_AbortSigMask
)
4940 KPRINTF(1, ("Kill signal detected!\n"));
4941 Signal(FindTask(NULL
), pps
->pps_AbortSigMask
& sigmask
);
4949 ioerr
= psdWaitPipe(pp
);
4950 pps
->pps_ActivePipe
= NULL
;
4951 AddTail(&pps
->pps_FreePipes
, &pp
->pp_Msg
.mn_Node
);
4954 pps
->pps_Error
= ioerr
;
4955 if(ioerr
!= UHIOERR_TIMEOUT
)
4957 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) "StreamWrite",
4958 "Packet(%s) failed: %s (%ld)", (STRPTR
) "u",
4959 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
4962 actual
= pp
->pp_IOReq
.iouh_Actual
;
4965 KPRINTF(2, ("No free pipe!\n"));
4968 ReleaseSemaphore(&pps
->pps_AccessLock
);
4974 /* /// "psdStreamFlush()" */
4975 AROS_LH1(LONG
, psdStreamFlush
,
4976 AROS_LHA(struct PsdPipeStream
*, pps
, A1
),
4977 LIBBASETYPEPTR
, ps
, 76, psd
)
4985 KPRINTF(2, ("psdStreamFlush(%p)\n", pps
));
4990 ObtainSemaphore(&pps
->pps_AccessLock
);
4992 if(pps
->pps_Endpoint
->pep_Direction
)
4995 KPRINTF(2, ("Flushing in...\n"));
4996 for(cnt
= 0; cnt
< pps
->pps_NumPipes
; cnt
++)
4998 psdAbortPipe(pps
->pps_Pipes
[cnt
]);
5000 for(cnt
= 0; cnt
< pps
->pps_NumPipes
; cnt
++)
5002 psdWaitPipe(pps
->pps_Pipes
[cnt
]);
5004 pp
= (struct PsdPipe
*) pps
->pps_ReadyPipes
.lh_Head
;
5005 while(pp
->pp_Msg
.mn_Node
.ln_Succ
)
5007 Remove(&pp
->pp_Msg
.mn_Node
);
5008 AddTail(&pps
->pps_FreePipes
, &pp
->pp_Msg
.mn_Node
);
5009 pp
= (struct PsdPipe
*) pps
->pps_ReadyPipes
.lh_Head
;
5011 while((pp
= (struct PsdPipe
*) GetMsg(pps
->pps_MsgPort
)))
5013 AddTail(&pps
->pps_FreePipes
, &pp
->pp_Msg
.mn_Node
);
5015 pps
->pps_ReqBytes
= 0;
5016 pps
->pps_BytesPending
= 0;
5017 pps
->pps_Offset
= 0;
5021 pp
= (struct PsdPipe
*) pps
->pps_FreePipes
.lh_Head
;
5022 if(pp
->pp_Msg
.mn_Node
.ln_Succ
)
5025 if(pps
->pps_BytesPending
)
5027 KPRINTF(2, ("Flushing out %ld...\n", pps
->pps_BytesPending
));
5028 Remove(&pp
->pp_Msg
.mn_Node
);
5029 ioerr
= psdDoPipe(pp
, pps
->pps_Buffer
, pps
->pps_BytesPending
);
5030 AddTail(&pps
->pps_FreePipes
, &pp
->pp_Msg
.mn_Node
);
5031 pps
->pps_BytesPending
= 0;
5034 pps
->pps_Error
= ioerr
;
5035 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) "StreamFlush",
5036 "Packet(%s) failed: %s (%ld)", (STRPTR
) "f",
5037 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
5041 KPRINTF(2, ("Nothing to flush\n"));
5045 ReleaseSemaphore(&pps
->pps_AccessLock
);
5051 /* /// "psdGetStreamError()" */
5052 AROS_LH1(LONG
, psdGetStreamError
,
5053 AROS_LHA(struct PsdPipeStream
*, pps
, A1
),
5054 LIBBASETYPEPTR
, ps
, 77, psd
)
5057 KPRINTF(1, ("psdGetStreamError(%p)\n", pps
));
5060 return((LONG
) pps
->pps_Error
);
5068 /* *** Realtime Iso */
5070 /* /// "psdAllocRTIsoHandler()" */
5071 AROS_LH2(struct PsdRTIsoHandler
*, psdAllocRTIsoHandlerA
,
5072 AROS_LHA(struct PsdEndpoint
*, pep
, A0
),
5073 AROS_LHA(struct TagItem
*, tags
, A1
),
5074 LIBBASETYPEPTR
, ps
, 93, psd
)
5077 struct PsdRTIsoHandler
*prt
;
5081 KPRINTF(2, ("psdAllocRTIso(%p, %p)\n", pep
, tags
));
5086 if(pep
->pep_TransType
!= USEAF_ISOCHRONOUS
)
5090 if(!(pep
->pep_Interface
->pif_Config
->pc_Device
->pd_Hardware
->phw_Capabilities
& UHCF_RT_ISO
))
5092 psdAddErrorMsg0(RETURN_FAIL
, (STRPTR
) GM_UNIQUENAME(libname
), "Your HW controller driver does not support realtime iso transfers. Sorry.");
5095 if((prt
= psdAllocVec(sizeof(struct PsdRTIsoHandler
))))
5097 prt
->prt_Device
= pep
->pep_Interface
->pif_Config
->pc_Device
;
5098 prt
->prt_Endpoint
= pep
;
5099 prt
->prt_RTIso
.urti_OutPrefetch
= 2048;
5100 if((pp
= prt
->prt_Pipe
= psdAllocPipe(prt
->prt_Device
, (struct MsgPort
*) 0xffffffff, pep
)))
5102 pp
->pp_MsgPort
= pp
->pp_Msg
.mn_ReplyPort
= NULL
;
5103 psdSetAttrsA(PGA_RTISO
, prt
, tags
);
5104 pp
->pp_IOReq
.iouh_Req
.io_Command
= UHCMD_ADDISOHANDLER
;
5105 pp
->pp_IOReq
.iouh_Data
= &prt
->prt_RTIso
;
5106 // hardware must support quick IO for this to work!
5107 ioerr
= DoIO((struct IORequest
*) &pp
->pp_IOReq
);
5111 AddTail(&prt
->prt_Device
->pd_RTIsoHandlers
, &prt
->prt_Node
);
5115 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
5116 "Adding RT Iso Handler failed: %s (%ld)",
5117 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
5119 psdFreePipe(prt
->prt_Pipe
);
5128 /* /// "psdFreeRTIsoHandler()" */
5129 AROS_LH1(void, psdFreeRTIsoHandler
,
5130 AROS_LHA(struct PsdRTIsoHandler
*, prt
, A1
),
5131 LIBBASETYPEPTR
, ps
, 94, psd
)
5141 Remove(&prt
->prt_Node
);
5144 pp
->pp_IOReq
.iouh_Req
.io_Command
= UHCMD_REMISOHANDLER
;
5145 DoIO((struct IORequest
*) &pp
->pp_IOReq
);
5152 /* /// "psdStartRTIso()" */
5153 AROS_LH1(LONG
, psdStartRTIso
,
5154 AROS_LHA(struct PsdRTIsoHandler
*, prt
, A1
),
5155 LIBBASETYPEPTR
, ps
, 95, psd
)
5163 return UHIOERR_BADPARAMS
;
5166 if(pp
->pp_Device
->pd_Flags
& PDFF_SUSPENDED
)
5168 // make sure the device is up and running before trying to send a new pipe
5169 psdResumeDevice(pp
->pp_Device
);
5171 pp
->pp_IOReq
.iouh_Req
.io_Command
= UHCMD_STARTRTISO
;
5172 ioerr
= DoIO((struct IORequest
*) &pp
->pp_IOReq
);
5175 ++pp
->pp_Device
->pd_IOBusyCount
;
5182 /* /// "psdStopRTIso()" */
5183 AROS_LH1(LONG
, psdStopRTIso
,
5184 AROS_LHA(struct PsdRTIsoHandler
*, prt
, A1
),
5185 LIBBASETYPEPTR
, ps
, 96, psd
)
5193 return UHIOERR_BADPARAMS
;
5196 pp
->pp_IOReq
.iouh_Req
.io_Command
= UHCMD_STOPRTISO
;
5197 ioerr
= DoIO((struct IORequest
*) &pp
->pp_IOReq
);
5200 --pp
->pp_Device
->pd_IOBusyCount
;
5207 /* *** Classes *** */
5209 /* /// "psdAddClass()" */
5210 AROS_LH2(struct PsdUsbClass
*, psdAddClass
,
5211 AROS_LHA(STRPTR
, name
, A1
),
5212 AROS_LHA(ULONG
, vers
, D0
),
5213 LIBBASETYPEPTR
, ps
, 35, psd
)
5216 struct Library
*cls
= NULL
;
5217 struct PsdUsbClass
*puc
;
5221 STRPTR origname
= name
;
5222 STRPTR evilmsg
[8] = { "Say hello to %s V%ld.%ld (%s).",
5223 "Whoah! %s V%ld.%ld surprised as %s.",
5224 "The door bell rang for %s V%ld.%ld (%s).",
5225 "Welcome %s V%ld.%ld (%s) to the party.",
5227 "Don't laugh at %s V%ld.%ld for %s.",
5228 "Time has come for %s V%ld.%ld (%s) to join the show.",
5229 "Start blaming %s V%ld.%ld for helping at %s.",
5230 "Ain't %s V%ld.%ld useful for %s?" };
5232 KPRINTF(5, ("psdAddClass(%s, %ld)\n", name
, vers
));
5236 if((cls
= OpenLibrary(name
, vers
)))
5242 if((*name
== '/') || (*name
== ':'))
5252 if(FindName(&ps
->ps_Classes
, cls
->lib_Node
.ln_Name
))
5255 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
5256 "Attempted to add class %s twice. Nothing is good enough for people like you.",
5258 KPRINTF(20, ("attempt to add class twice!\n"));
5263 if((puc
= psdAllocVec(sizeof(struct PsdUsbClass
))))
5266 puc
->puc_ClassBase
= cls
;
5267 puc
->puc_Node
.ln_Name
= puc
->puc_ClassName
= psdCopyStr(cls
->lib_Node
.ln_Name
);
5268 puc
->puc_FullPath
= psdCopyStr(origname
);
5270 usbGetAttrs(UGA_CLASS
, NULL
,
5271 UCCA_Priority
, &pri
,
5272 UCCA_Description
, &desc
,
5275 puc
->puc_Node
.ln_Pri
= pri
;
5276 psdLockWritePBase();
5277 Enqueue(&ps
->ps_Classes
, &puc
->puc_Node
);
5279 msgoff
= ps
->ps_FunnyCount
++ & 7;
5281 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
5283 cls
->lib_Node
.ln_Name
, cls
->lib_Version
, cls
->lib_Revision
, desc
);
5284 psdSendEvent(EHMB_ADDCLASS
, puc
, NULL
);
5294 /* /// "psdRemClass()" */
5295 AROS_LH1(void, psdRemClass
,
5296 AROS_LHA(struct PsdUsbClass
*, puc
, A1
),
5297 LIBBASETYPEPTR
, ps
, 36, psd
)
5300 KPRINTF(5, ("psdRemClass(%p)\n", puc
));
5301 psdLockWritePBase();
5302 Remove(&puc
->puc_Node
);
5305 /* Check if there are still bindings remaining */
5306 while(puc
->puc_UseCnt
)
5308 struct PsdDevice
*pd
;
5309 struct PsdConfig
*pc
;
5310 struct PsdInterface
*pif
;
5312 KPRINTF(20, ("This should never happen: Class %s still in use (%ld), can't close!\n",
5313 puc
->puc_ClassBase
->lib_Node
.ln_Name
, puc
->puc_UseCnt
));
5315 /* Well, try to release the open bindings in a best effort attempt */
5318 while((pd
= psdGetNextDevice(pd
)))
5320 if(pd
->pd_DevBinding
&& (pd
->pd_ClsBinding
== puc
) && (!(pd
->pd_Flags
& PDFF_APPBINDING
)))
5323 psdReleaseDevBinding(pd
);
5325 pd
= NULL
; /* restart */
5328 pc
= (struct PsdConfig
*) pd
->pd_Configs
.lh_Head
;
5329 while(pc
->pc_Node
.ln_Succ
)
5331 pif
= (struct PsdInterface
*) pc
->pc_Interfaces
.lh_Head
;
5332 while(pif
->pif_Node
.ln_Succ
)
5334 if(pif
->pif_IfBinding
&& (pif
->pif_ClsBinding
== puc
))
5337 psdReleaseIfBinding(pif
);
5339 pd
= NULL
; /* restart */
5342 pif
= (struct PsdInterface
*) pif
->pif_Node
.ln_Succ
;
5344 pc
= (struct PsdConfig
*) pc
->pc_Node
.ln_Succ
;
5350 psdAddErrorMsg(RETURN_FAIL
, (STRPTR
) GM_UNIQUENAME(libname
),
5351 "This should never happen! Class %s still in use (cnt=%ld). Could not get rid of it! Sorry, we're broke.",
5352 puc
->puc_ClassBase
->lib_Node
.ln_Name
, puc
->puc_UseCnt
);
5354 /*psdDelayMS(2000);*/
5357 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
5358 "I shot class %s, but I didn't kill the deputy.",
5359 puc
->puc_ClassBase
->lib_Node
.ln_Name
);
5360 CloseLibrary(puc
->puc_ClassBase
);
5361 psdFreeVec(puc
->puc_ClassName
);
5362 psdFreeVec(puc
->puc_FullPath
);
5364 psdSendEvent(EHMB_REMCLASS
, puc
, NULL
);
5369 /* *** Error Msgs *** */
5371 /* /// "psdAddErrorMsgA()" */
5372 AROS_LH4(struct PsdErrorMsg
*, psdAddErrorMsgA
,
5373 AROS_LHA(UWORD
, level
, D0
),
5374 AROS_LHA(STRPTR
, origin
, A0
),
5375 AROS_LHA(STRPTR
, fmtstr
, A1
),
5376 AROS_LHA(IPTR
*, fmtdata
, A2
),
5377 LIBBASETYPEPTR
, ps
, 40, psd
)
5380 struct PsdErrorMsg
*pem
;
5381 if(((!ps
->ps_GlobalCfg
->pgc_LogInfo
) && (level
< RETURN_WARN
)) ||
5382 ((!ps
->ps_GlobalCfg
->pgc_LogWarning
) && (level
>= RETURN_WARN
) && (level
< RETURN_ERROR
)) ||
5383 ((!ps
->ps_GlobalCfg
->pgc_LogError
) && (level
>= RETURN_ERROR
) && (level
< RETURN_FAIL
)) ||
5384 ((!ps
->ps_GlobalCfg
->pgc_LogFailure
) && (level
>= RETURN_FAIL
)))
5388 if((pem
= psdAllocVec(sizeof(struct PsdErrorMsg
))))
5391 pem
->pem_Level
= level
;
5392 if((pem
->pem_Origin
= psdCopyStr(origin
)))
5394 if((pem
->pem_Msg
= psdCopyStrFmtA(fmtstr
, fmtdata
)))
5396 if (ps
->ps_Flags
& PSF_KLOG
) {
5397 KPrintF("[%s] %s\n", origin
, pem
->pem_Msg
);
5402 DateStamp(&pem
->pem_DateStamp
);
5404 struct timerequest tr
= ps
->ps_TimerIOReq
;
5405 tr
.tr_node
.io_Command
= TR_GETSYSTIME
;
5406 DoIO((struct IORequest
*) &tr
);
5407 pem
->pem_DateStamp
.ds_Days
= tr
.tr_time
.tv_secs
/ (24*60*60);
5408 pem
->pem_DateStamp
.ds_Minute
= (tr
.tr_time
.tv_secs
/ 60) % 60;
5409 pem
->pem_DateStamp
.ds_Tick
= (tr
.tr_time
.tv_secs
% 60) * 50;
5412 AddTail(&ps
->ps_ErrorMsgs
, &pem
->pem_Node
);
5414 psdSendEvent(EHMB_ADDERRORMSG
, pem
, NULL
);
5417 psdFreeVec(pem
->pem_Origin
);
5426 /* /// "psdRemErrorMsg()" */
5427 AROS_LH1(void, psdRemErrorMsg
,
5428 AROS_LHA(struct PsdErrorMsg
*, pem
, A0
),
5429 LIBBASETYPEPTR
, ps
, 41, psd
)
5432 KPRINTF(1, ("psdRemErrorMsg()\n"));
5434 Remove(&pem
->pem_Node
);
5436 psdFreeVec(pem
->pem_Origin
);
5437 psdFreeVec(pem
->pem_Msg
);
5439 psdSendEvent(EHMB_REMERRORMSG
, pem
, NULL
);
5444 /* *** Bindings *** */
5446 /* /// "psdClassScan()" */
5447 AROS_LH0(void, psdClassScan
,
5448 LIBBASETYPEPTR
, ps
, 37, psd
)
5451 struct PsdHardware
*phw
;
5452 struct PsdDevice
*pd
;
5453 struct PsdUsbClass
*puc
;
5457 if((FindTask(NULL
)->tc_Node
.ln_Type
!= NT_PROCESS
) && (!ps
->ps_ConfigRead
))
5459 // it's the first time we were reading the config and DOS was not available
5460 ps
->ps_StartedAsTask
= TRUE
;
5463 puc
= (struct PsdUsbClass
*) ps
->ps_Classes
.lh_Head
;
5464 if(!puc
->puc_Node
.ln_Succ
)
5466 psdAddErrorMsg0(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "ClassScan attempted with no classes installed!");
5471 phw
= (struct PsdHardware
*) ps
->ps_Hardware
.lh_Head
;
5472 while(phw
->phw_Node
.ln_Succ
)
5474 if((pd
= phw
->phw_RootDevice
))
5476 // for the root, do it ourselves, the rest is done by each hub task
5477 psdHubClassScan(pd
);
5479 phw
= (struct PsdHardware
*) phw
->phw_Node
.ln_Succ
;
5482 //psdSendEvent(EHMB_CLSSCANRDY, NULL, NULL);
5483 KPRINTF(5, ("************ Scanning finished!\n"));
5488 /* /// "psdDoHubMethodA()" */
5489 AROS_LH3(LONG
, psdDoHubMethodA
,
5490 AROS_LHA(struct PsdDevice
*, pd
, A0
),
5491 AROS_LHA(ULONG
, methodid
, D0
),
5492 AROS_LHA(APTR
, methoddata
, A1
),
5493 LIBBASETYPEPTR
, ps
, 92, psd
)
5496 struct PsdUsbClass
*puc
;
5497 KPRINTF(2, ("psdDoHubMethodA(%p)\n", pd
));
5503 if((pd
->pd_Hub
->pd_DevBinding
) && (puc
= pd
->pd_Hub
->pd_ClsBinding
))
5505 return(usbDoMethodA(methodid
, methoddata
));
5514 /* /// "psdClaimAppBindingA()" */
5515 AROS_LH1(struct PsdAppBinding
*, psdClaimAppBindingA
,
5516 AROS_LHA(struct TagItem
*, tags
, A1
),
5517 LIBBASETYPEPTR
, ps
, 45, psd
)
5520 struct PsdDevice
*pd
;
5521 struct PsdConfig
*pc
;
5522 struct PsdInterface
*pif
;
5523 struct PsdDevice
*hubpd
;
5524 struct PsdAppBinding tmppab
;
5525 struct PsdAppBinding
*pab
= NULL
;
5526 struct PsdUsbClass
*puc
;
5530 KPRINTF(2, ("psdClaimAppBindingA(%p)\n", tags
));
5532 tmppab
.pab_Device
= NULL
;
5533 tmppab
.pab_ReleaseHook
= NULL
;
5534 tmppab
.pab_Task
= NULL
;
5535 tmppab
.pab_ForceRelease
= FALSE
;
5536 psdSetAttrsA(PGA_APPBINDING
, &tmppab
, tags
);
5537 if(tmppab
.pab_Device
&& tmppab
.pab_ReleaseHook
)
5539 pd
= tmppab
.pab_Device
;
5541 // force release of other bindings first
5542 if(tmppab
.pab_ForceRelease
)
5544 /* If there are bindings, get rid of them. */
5545 if(pd
->pd_DevBinding
)
5547 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
5548 "%s really wants to bind to %s, so I'm letting the old binding go.",
5549 FindTask(NULL
)->tc_Node
.ln_Name
,
5552 psdReleaseDevBinding(pd
);
5554 pc
= (struct PsdConfig
*) pd
->pd_Configs
.lh_Head
;
5555 while(pc
->pc_Node
.ln_Succ
)
5557 pif
= (struct PsdInterface
*) pc
->pc_Interfaces
.lh_Head
;
5558 while(pif
->pif_Node
.ln_Succ
)
5560 if(pif
->pif_IfBinding
)
5562 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
5563 "%s really wants to bind to %s, so I'm letting the old binding go.",
5564 FindTask(NULL
)->tc_Node
.ln_Name
,
5566 psdReleaseIfBinding(pif
);
5568 pif
= (struct PsdInterface
*) pif
->pif_Node
.ln_Succ
;
5570 pc
= (struct PsdConfig
*) pc
->pc_Node
.ln_Succ
;
5575 if(!hubpd
) // claim app binding at the root hub -- improbable, but possible.
5577 pab
= psdHubClaimAppBindingA(tags
);
5579 if((binding
= hubpd
->pd_DevBinding
) && (puc
= hubpd
->pd_ClsBinding
))
5581 pab
= (struct PsdAppBinding
*) usbDoMethod(UCM_HubClaimAppBinding
, binding
, tags
);
5586 // fill in task names
5587 pab
->pab_Task
= FindTask(NULL
);
5588 pab
->pab_Node
.ln_Name
= pab
->pab_Task
->tc_Node
.ln_Name
;
5589 psdSendEvent(EHMB_ADDBINDING
, pd
, NULL
);
5598 /* /// "psdReleaseAppBinding()" */
5599 AROS_LH1(void, psdReleaseAppBinding
,
5600 AROS_LHA(struct PsdAppBinding
*, pab
, A0
),
5601 LIBBASETYPEPTR
, ps
, 46, psd
)
5604 struct PsdDevice
*pd
;
5605 struct PsdDevice
*hubpd
;
5606 struct PsdUsbClass
*puc
;
5609 KPRINTF(2, ("psdReleaseAppBinding(%p)\n", pab
));
5613 pd
= pab
->pab_Device
;
5615 if(!hubpd
) // release binding of hub (improbable)
5617 psdHubReleaseDevBinding(pd
);
5620 if((binding
= hubpd
->pd_DevBinding
) && (puc
= hubpd
->pd_ClsBinding
))
5622 usbDoMethod(UCM_HubReleaseDevBinding
, binding
, pd
);
5629 /* /// "psdReleaseDevBinding()" */
5630 AROS_LH1(void, psdReleaseDevBinding
,
5631 AROS_LHA(struct PsdDevice
*, pd
, A0
),
5632 LIBBASETYPEPTR
, ps
, 50, psd
)
5635 struct PsdUsbClass
*puc
;
5636 struct PsdDevice
*hubpd
;
5639 KPRINTF(5, ("psdReleaseDevBinding(%p)\n", pd
));
5640 if(pd
->pd_DevBinding
)
5643 if(!hubpd
) // release binding of hub
5645 psdHubReleaseDevBinding(pd
);
5648 if((binding
= hubpd
->pd_DevBinding
) && (puc
= hubpd
->pd_ClsBinding
))
5650 usbDoMethod(UCM_HubReleaseDevBinding
, binding
, pd
);
5657 /* /// "psdReleaseIfBinding()" */
5658 AROS_LH1(void, psdReleaseIfBinding
,
5659 AROS_LHA(struct PsdInterface
*, pif
, A0
),
5660 LIBBASETYPEPTR
, ps
, 51, psd
)
5663 struct PsdUsbClass
*puc
;
5664 struct PsdDevice
*hubpd
;
5667 KPRINTF(5, ("psdReleaseIfBinding(%p)\n", pif
));
5668 if(pif
->pif_IfBinding
&& pif
->pif_ClsBinding
)
5670 hubpd
= pif
->pif_Config
->pc_Device
->pd_Hub
;
5671 if(!hubpd
) // release binding of hub (improbable)
5673 psdHubReleaseIfBinding(pif
);
5676 if((binding
= hubpd
->pd_DevBinding
) && (puc
= hubpd
->pd_ClsBinding
))
5678 usbDoMethod(UCM_HubReleaseIfBinding
, binding
, pif
);
5685 /* /// "psdUnbindAll()" */
5686 AROS_LH0(void, psdUnbindAll
,
5687 LIBBASETYPEPTR
, ps
, 61, psd
)
5690 struct PsdHardware
*phw
;
5691 struct PsdDevice
*pd
;
5692 struct PsdConfig
*pc
;
5693 struct PsdInterface
*pif
;
5696 KPRINTF(10, ("pUnbindAll()\n"));
5697 /* FIXME What happens if devices or hardware gets removed during the process? Need notify semaphore */
5702 phw
= (struct PsdHardware
*) ps
->ps_Hardware
.lh_Head
;
5703 while(phw
->phw_Node
.ln_Succ
)
5705 pd
= (struct PsdDevice
*) phw
->phw_Devices
.lh_Head
;
5706 while(pd
->pd_Node
.ln_Succ
)
5708 /* If there are bindings, get rid of them. */
5709 if(pd
->pd_DevBinding
)
5712 psdReleaseDevBinding(pd
);
5717 pc
= (struct PsdConfig
*) pd
->pd_Configs
.lh_Head
;
5718 while(pc
->pc_Node
.ln_Succ
)
5720 pif
= (struct PsdInterface
*) pc
->pc_Interfaces
.lh_Head
;
5721 while(pif
->pif_Node
.ln_Succ
)
5723 if(pif
->pif_IfBinding
)
5726 psdReleaseIfBinding(pif
);
5731 pif
= (struct PsdInterface
*) pif
->pif_Node
.ln_Succ
;
5737 pc
= (struct PsdConfig
*) pc
->pc_Node
.ln_Succ
;
5743 pd
= (struct PsdDevice
*) pd
->pd_Node
.ln_Succ
;
5749 phw
= (struct PsdHardware
*) phw
->phw_Node
.ln_Succ
;
5757 /* /// "psdHubClassScan()" */
5758 AROS_LH1(void, psdHubClassScan
,
5759 AROS_LHA(struct PsdDevice
*, pd
, A0
),
5760 LIBBASETYPEPTR
, ps
, 82, psd
)
5763 struct PsdUsbClass
*puc
;
5764 struct PsdConfig
*pc
;
5765 struct PsdInterface
*pif
;
5766 struct PsdInterface
*firstpif
;
5767 struct PsdPipe
*pp
= NULL
;
5774 KPRINTF(5, ("psdClassScan()\n"));
5776 if(!(mp
= CreateMsgPort()))
5781 psdLockWriteDevice(pd
);
5782 while(!(pd
->pd_PoPoCfg
.poc_NoClassBind
|| pd
->pd_DevBinding
))
5784 if(!(pp
= psdAllocPipe(pd
, mp
, NULL
)))
5788 KPRINTF(5, ("Doing ClassScan on Device: %s\n", pd
->pd_ProductStr
));
5790 /* First look if there is any interface binding. We may not change
5791 the current config in this case! */
5792 pc
= (struct PsdConfig
*) pd
->pd_Configs
.lh_Head
;
5793 while(pc
->pc_Node
.ln_Succ
)
5795 pif
= (struct PsdInterface
*) pc
->pc_Interfaces
.lh_Head
;
5797 while(pif
->pif_Node
.ln_Succ
)
5799 if(pif
->pif_IfBinding
)
5801 hasifbinding
= pc
->pc_CfgNum
;
5804 pif
= (struct PsdInterface
*) pif
->pif_Node
.ln_Succ
;
5806 pc
= (struct PsdConfig
*) pc
->pc_Node
.ln_Succ
;
5809 owner
= psdGetForcedBinding(pd
->pd_IDString
, NULL
);
5810 if((!hasifbinding
) && owner
)
5812 puc
= (struct PsdUsbClass
*) ps
->ps_Classes
.lh_Head
;
5813 while(puc
->puc_Node
.ln_Succ
)
5815 if(!strcmp(owner
, puc
->puc_ClassName
))
5817 if((pd
->pd_DevBinding
= (APTR
) usbDoMethod(UCM_ForceDeviceBinding
, pd
)))
5819 pd
->pd_ClsBinding
= puc
;
5821 psdSendEvent(EHMB_ADDBINDING
, pd
, NULL
);
5823 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
5824 "Forced device binding of %s to %s failed.", pd
->pd_ProductStr
, owner
);
5828 puc
= (struct PsdUsbClass
*) puc
->puc_Node
.ln_Succ
;
5830 /* no more scanning required, abort here */
5834 /* Second attempt */
5835 pc
= (struct PsdConfig
*) pd
->pd_Configs
.lh_Head
;
5836 while(pc
->pc_Node
.ln_Succ
)
5838 if((!hasifbinding
) || (hasifbinding
== pc
->pc_CfgNum
))
5840 /* If the current config is not the one selected, change it */
5841 if(pd
->pd_CurrCfg
!= pc
->pc_CfgNum
)
5843 psdSetDeviceConfig(pp
, pc
->pc_CfgNum
);
5845 KPRINTF(5, (" Config %ld\n", pc
->pc_CfgNum
));
5846 /* If something went wrong above, we must exclude this config */
5847 if(pd
->pd_CurrCfg
== pc
->pc_CfgNum
)
5849 pif
= (struct PsdInterface
*) pc
->pc_Interfaces
.lh_Head
;
5850 while(pif
->pif_Node
.ln_Succ
)
5852 KPRINTF(5, (" Interface %ld\n", pif
->pif_IfNum
));
5855 if(!pif
->pif_IfBinding
)
5860 if(!psdSetAltInterface(pp
, pif
))
5862 pif
->pif_IfBinding
= NULL
;
5863 /* Okay, this alternate setting failed. Try to get next one */
5866 pif
= (struct PsdInterface
*) pif
->pif_Node
.ln_Succ
;
5867 if(pif
->pif_Node
.ln_Succ
)
5869 KPRINTF(5, ("CONT!\n"));
5872 KPRINTF(5, ("BREAK!\n"));
5878 owner
= psdGetForcedBinding(pd
->pd_IDString
, pif
->pif_IDString
);
5879 puc
= (struct PsdUsbClass
*) ps
->ps_Classes
.lh_Head
;
5880 while(puc
->puc_Node
.ln_Succ
)
5882 KPRINTF(5, (">>>PING %s!\n", puc
->puc_ClassName
));
5885 if(!strcmp(owner
, puc
->puc_ClassName
))
5887 binding
= (APTR
) usbDoMethod(UCM_ForceInterfaceBinding
, pif
);
5890 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
5891 "Forced interface binding of %s to %s failed.", pd
->pd_ProductStr
, owner
);
5896 puc
= (struct PsdUsbClass
*) puc
->puc_Node
.ln_Succ
;
5900 binding
= (APTR
) usbDoMethod(UCM_AttemptInterfaceBinding
, pif
);
5903 KPRINTF(5, ("<<<PONG!!\n"));
5906 KPRINTF(5, ("Got binding!\n"));
5907 /* Find root config structure */
5908 pif
= (struct PsdInterface
*) pc
->pc_Interfaces
.lh_Head
;
5909 while(pif
->pif_Node
.ln_Succ
)
5911 if(pif
->pif_IfNum
== firstpif
->pif_IfNum
)
5915 pif
= (struct PsdInterface
*) pif
->pif_Node
.ln_Succ
;
5917 if(!pif
->pif_Node
.ln_Succ
)
5919 KPRINTF(5, ("Fucked it up!\n"));
5920 psdAddErrorMsg0(RETURN_FAIL
, (STRPTR
) GM_UNIQUENAME(libname
), "Something incredibly stupid happend. I've given up.");
5924 pif
->pif_IfBinding
= binding
;
5925 pif
->pif_ClsBinding
= puc
;
5926 hasifbinding
= pc
->pc_CfgNum
;
5928 psdSendEvent(EHMB_ADDBINDING
, pd
, NULL
);
5933 puc
= (struct PsdUsbClass
*) puc
->puc_Node
.ln_Succ
;
5939 //break; /* FIXME: DISABLED ALTSCANNING */
5940 /* Check alternate setting */
5941 if(pif
->pif_AlterIfs
.lh_Head
->ln_Succ
)
5943 /* There are some alternative interfaces, start at top */
5944 pif
= (struct PsdInterface
*) pif
->pif_AlterIfs
.lh_Head
;
5947 } while(pif
!= firstpif
);
5948 //pif->pif_IfBinding = binding;
5951 psdSetAltInterface(pp
, pif
);
5953 /* Hohum, search current main interface then */
5954 pif
= (struct PsdInterface
*) pc
->pc_Interfaces
.lh_Head
;
5955 while(pif
->pif_Node
.ln_Succ
)
5957 if(pif
->pif_IfNum
== firstpif
->pif_IfNum
)
5961 pif
= (struct PsdInterface
*) pif
->pif_Node
.ln_Succ
;
5964 pif
= (struct PsdInterface
*) pif
->pif_Node
.ln_Succ
;
5968 KPRINTF(5, ("End, next ConfigCheck!\n"));
5969 pc
= (struct PsdConfig
*) pc
->pc_Node
.ln_Succ
;
5971 /* Could not establish interface binding, try device binding then */
5975 //pd->pd_DevBinding = (APTR) ~0UL;
5977 owner
= psdGetForcedBinding(pd
->pd_IDString
, NULL
);
5978 puc
= (struct PsdUsbClass
*) ps
->ps_Classes
.lh_Head
;
5979 while(puc
->puc_Node
.ln_Succ
)
5984 if(!strcmp(owner
, puc
->puc_ClassName
))
5986 binding
= (APTR
) usbDoMethod(UCM_ForceDeviceBinding
, pd
, TAG_END
);
5989 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
5990 "Forced device binding of %s to %s failed.", pd
->pd_ProductStr
, owner
);
5995 puc
= (struct PsdUsbClass
*) puc
->puc_Node
.ln_Succ
;
5999 binding
= (APTR
) usbDoMethod(UCM_AttemptDeviceBinding
, pd
);
6003 pd
->pd_DevBinding
= binding
;
6004 pd
->pd_ClsBinding
= puc
;
6006 psdSendEvent(EHMB_ADDBINDING
, pd
, NULL
);
6009 puc
= (struct PsdUsbClass
*) puc
->puc_Node
.ln_Succ
;
6011 pd
->pd_DevBinding
= binding
;
6019 // call hub class scan code
6020 if((binding
= pd
->pd_DevBinding
) && (puc
= pd
->pd_ClsBinding
))
6022 usbDoMethod(UCM_HubClassScan
, binding
);
6024 psdUnlockDevice(pd
);
6031 /* /// "psdHubClaimAppBindingA()" */
6032 AROS_LH1(struct PsdAppBinding
*, psdHubClaimAppBindingA
,
6033 AROS_LHA(struct TagItem
*, tags
, A1
),
6034 LIBBASETYPEPTR
, ps
, 83, psd
)
6037 struct PsdDevice
*pd
;
6038 struct PsdAppBinding
*pab
;
6039 struct PsdConfig
*pc
;
6040 struct PsdInterface
*pif
;
6042 BOOL hasbinding
= FALSE
;
6043 KPRINTF(2, ("psdHubClaimAppBindingA(%p)\n", tags
));
6045 if((pab
= psdAllocVec(sizeof(struct PsdAppBinding
))))
6047 psdSetAttrsA(PGA_APPBINDING
, pab
, tags
);
6048 if(pab
->pab_Device
&& pab
->pab_ReleaseHook
)
6050 pd
= pab
->pab_Device
;
6051 if(pd
->pd_DevBinding
)
6055 pc
= (struct PsdConfig
*) pd
->pd_Configs
.lh_Head
;
6056 while(pc
->pc_Node
.ln_Succ
)
6058 pif
= (struct PsdInterface
*) pc
->pc_Interfaces
.lh_Head
;
6060 while(pif
->pif_Node
.ln_Succ
)
6062 if(pif
->pif_IfBinding
)
6067 pif
= (struct PsdInterface
*) pif
->pif_Node
.ln_Succ
;
6069 pc
= (struct PsdConfig
*) pc
->pc_Node
.ln_Succ
;
6074 pd
->pd_Flags
|= PDFF_APPBINDING
;
6075 pd
->pd_DevBinding
= pab
;
6076 pd
->pd_ClsBinding
= NULL
;
6087 /* /// "psdHubReleaseDevBinding()" */
6088 AROS_LH1(void, psdHubReleaseDevBinding
,
6089 AROS_LHA(struct PsdDevice
*, pd
, A0
),
6090 LIBBASETYPEPTR
, ps
, 84, psd
)
6093 struct PsdUsbClass
*puc
;
6095 struct PsdAppBinding
*pab
;
6097 KPRINTF(5, ("psdHubReleaseDevBinding(%p)\n", pd
));
6100 psdLockWriteDevice(pd
);
6101 if((binding
= pd
->pd_DevBinding
))
6103 pd
->pd_DevBinding
= NULL
;
6104 if(pd
->pd_Flags
& PDFF_APPBINDING
)
6106 pab
= (struct PsdAppBinding
*) binding
;
6107 CallHookPkt(pab
->pab_ReleaseHook
, pab
, (APTR
) pab
->pab_UserData
);
6108 pd
->pd_ClsBinding
= NULL
;
6109 pd
->pd_Flags
&= ~PDFF_APPBINDING
;
6111 psdSendEvent(EHMB_REMBINDING
, pd
, NULL
);
6113 puc
= pd
->pd_ClsBinding
;
6116 pd
->pd_ClsBinding
= NULL
;
6117 usbDoMethod(UCM_ReleaseDeviceBinding
, binding
);
6119 psdSendEvent(EHMB_REMBINDING
, pd
, NULL
);
6123 psdUnlockDevice(pd
);
6129 /* /// "psdHubReleaseIfBinding()" */
6130 AROS_LH1(void, psdHubReleaseIfBinding
,
6131 AROS_LHA(struct PsdInterface
*, pif
, A0
),
6132 LIBBASETYPEPTR
, ps
, 85, psd
)
6135 struct PsdUsbClass
*puc
;
6136 struct PsdDevice
*pd
;
6139 KPRINTF(5, ("psdHubReleaseIfBinding(%p)\n", pif
));
6143 pd
= pif
->pif_Config
->pc_Device
;
6144 psdLockWriteDevice(pd
);
6145 if((binding
= pif
->pif_IfBinding
))
6147 pif
->pif_IfBinding
= NULL
;
6148 puc
= pif
->pif_ClsBinding
;
6151 pif
->pif_ClsBinding
= NULL
;
6152 usbDoMethod(UCM_ReleaseInterfaceBinding
, binding
);
6155 psdSendEvent(EHMB_REMBINDING
, pd
, NULL
);
6157 psdUnlockDevice(pd
);
6163 /* *** Events *** */
6165 /* /// "psdAddEventHandler()" */
6166 AROS_LH2(struct PsdEventHook
*, psdAddEventHandler
,
6167 AROS_LHA(struct MsgPort
*, mp
, A1
),
6168 AROS_LHA(ULONG
, msgmask
, D0
),
6169 LIBBASETYPEPTR
, ps
, 47, psd
)
6172 struct PsdEventHook
*peh
= NULL
;
6174 KPRINTF(5, ("psdAddEventHandler(%p, %p)\n", mp
, msgmask
));
6178 ObtainSemaphore(&ps
->ps_ReentrantLock
);
6179 if((peh
= psdAllocVec(sizeof(struct PsdEventHook
))))
6181 peh
->peh_MsgPort
= mp
;
6182 peh
->peh_MsgMask
= msgmask
;
6183 AddTail(&ps
->ps_EventHooks
, &peh
->peh_Node
);
6185 ReleaseSemaphore(&ps
->ps_ReentrantLock
);
6192 /* /// "psdRemEventHandler()" */
6193 AROS_LH1(void, psdRemEventHandler
,
6194 AROS_LHA(struct PsdEventHook
*, peh
, A0
),
6195 LIBBASETYPEPTR
, ps
, 48, psd
)
6198 struct Message
*msg
;
6200 KPRINTF(5, ("psdRemEventHandler(%p)\n", peh
));
6205 ObtainSemaphore(&ps
->ps_ReentrantLock
);
6206 Remove(&peh
->peh_Node
);
6207 while((msg
= GetMsg(peh
->peh_MsgPort
)))
6211 ReleaseSemaphore(&ps
->ps_ReentrantLock
);
6212 pGarbageCollectEvents(ps
);
6218 /* /// "psdSendEvent()" */
6219 AROS_LH3(void, psdSendEvent
,
6220 AROS_LHA(ULONG
, ehmt
, D0
),
6221 AROS_LHA(APTR
, param1
, A0
),
6222 AROS_LHA(APTR
, param2
, A1
),
6223 LIBBASETYPEPTR
, ps
, 49, psd
)
6226 struct PsdEventNote
*pen
;
6227 struct PsdEventHook
*peh
;
6228 ULONG msgmask
= (1L<<ehmt
);
6230 KPRINTF(1, ("psdSendEvent(%p, %p, %p)\n", ehmt
, param1
, param2
));
6232 pGarbageCollectEvents(ps
);
6233 ObtainSemaphore(&ps
->ps_ReentrantLock
);
6234 peh
= (struct PsdEventHook
*) ps
->ps_EventHooks
.lh_Head
;
6235 while(peh
->peh_Node
.ln_Succ
)
6237 if(peh
->peh_MsgMask
& msgmask
)
6239 if((pen
= psdAllocVec(sizeof(struct PsdEventNote
))))
6241 pen
->pen_Msg
.mn_ReplyPort
= &ps
->ps_EventReplyPort
;
6242 pen
->pen_Msg
.mn_Length
= sizeof(struct PsdEventNote
);
6243 pen
->pen_Event
= ehmt
;
6244 pen
->pen_Param1
= param1
;
6245 pen
->pen_Param2
= param2
;
6246 PutMsg(peh
->peh_MsgPort
, &pen
->pen_Msg
);
6249 peh
= (struct PsdEventHook
*) peh
->peh_Node
.ln_Succ
;
6251 ReleaseSemaphore(&ps
->ps_ReentrantLock
);
6256 /* *** Configuration *** */
6258 /* /// "psdReadCfg()" */
6259 AROS_LH2(BOOL
, psdReadCfg
,
6260 AROS_LHA(struct PsdIFFContext
*, pic
, A0
),
6261 AROS_LHA(APTR
, formdata
, A1
),
6262 LIBBASETYPEPTR
, ps
, 52, psd
)
6265 struct PsdIFFContext
*subpic
;
6268 ULONG
*buf
= formdata
;
6270 KPRINTF(10, ("psdReadCfg(%p, %p)\n", pic
, formdata
));
6272 pLockSemExcl(ps
, &ps
->ps_ConfigLock
);
6275 pic
= (struct PsdIFFContext
*) ps
->ps_ConfigRoot
.lh_Head
;
6276 if(!(pic
->pic_Node
.ln_Succ
))
6278 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6282 if((AROS_LONG2BE(*buf
) != ID_FORM
) || (AROS_LONG2BE(buf
[2]) != pic
->pic_FormID
))
6284 psdAddErrorMsg0(RETURN_FAIL
, (STRPTR
) GM_UNIQUENAME(libname
), "Tried to replace a cfg form with a chunk or with an alien form!");
6285 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6288 subpic
= (struct PsdIFFContext
*) pic
->pic_SubForms
.lh_Head
;
6289 while(subpic
->pic_Node
.ln_Succ
)
6291 pFreeForm(ps
, subpic
);
6292 subpic
= (struct PsdIFFContext
*) pic
->pic_SubForms
.lh_Head
;
6294 pic
->pic_ChunksLen
= 0;
6295 len
= (AROS_LONG2BE(buf
[1]) - 3) & ~1UL;
6299 if(!(pAddCfgChunk(ps
, pic
, buf
)))
6303 chlen
= (AROS_LONG2BE(buf
[1]) + 9) & ~1UL;
6305 buf
= (ULONG
*) (((UBYTE
*) buf
) + chlen
);
6309 psdAddErrorMsg0(RETURN_FAIL
, (STRPTR
) GM_UNIQUENAME(libname
), "Tried to add a nasty corrupted FORM chunk! Configuration is probably b0rken!");
6313 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6314 ps
->ps_CheckConfigReq
= TRUE
;
6320 /* /// "psdLoadCfgFromDisk()" */
6321 AROS_LH1(BOOL
, psdLoadCfgFromDisk
,
6322 AROS_LHA(STRPTR
, filename
, A1
),
6323 LIBBASETYPEPTR
, ps
, 79, psd
)
6327 BOOL loaded
= FALSE
;
6332 XPRINTF(10, ("Loading config file: %s\n", filename
));
6336 loaded
= psdLoadCfgFromDisk("ENV:Sys/poseidon.prefs");
6342 loaded
= psdLoadCfgFromDisk("ENVARC:Sys/poseidon.prefs");
6349 KPRINTF(1, ("dos.library not available yet\n"));
6353 filehandle
= Open(filename
, MODE_OLDFILE
);
6354 KPRINTF(1, ("File handle 0x%p\n", filehandle
));
6357 if(Read(filehandle
, formhead
, 12) == 12)
6359 KPRINTF(1, ("Read header\n"));
6360 if((AROS_LONG2BE(formhead
[0]) == ID_FORM
) && (AROS_LONG2BE(formhead
[2]) == IFFFORM_PSDCFG
))
6362 formlen
= AROS_LONG2BE(formhead
[1]);
6363 KPRINTF(1, ("Header OK, %lu bytes\n", formlen
));
6365 buf
= (ULONG
*) psdAllocVec(formlen
+ 8);
6368 buf
[0] = formhead
[0];
6369 buf
[1] = formhead
[1];
6370 buf
[2] = formhead
[2];
6371 if(Read(filehandle
, &buf
[3], formlen
- 4) == formlen
- 4)
6373 KPRINTF(1, ("Data read OK\n"));
6375 psdReadCfg(NULL
, buf
);
6378 KPRINTF(1, ("All done\n"));
6387 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
6388 "Failed to load config from '%s'!",
6393 ps
->ps_SavedConfigHash
= ps
->ps_ConfigHash
;
6400 /* /// "psdSaveCfgToDisk()" */
6401 AROS_LH2(BOOL
, psdSaveCfgToDisk
,
6402 AROS_LHA(STRPTR
, filename
, A1
),
6403 AROS_LHA(BOOL
, executable
, D0
),
6404 LIBBASETYPEPTR
, ps
, 80, psd
)
6413 saved
= psdSaveCfgToDisk("ENVARC:Sys/poseidon.prefs", FALSE
);
6414 saved
&= psdSaveCfgToDisk("ENV:Sys/poseidon.prefs", FALSE
);
6422 pLockSemShared(ps
, &ps
->ps_ConfigLock
);
6424 buf
= (ULONG
*) psdWriteCfg(NULL
);
6428 filehandle
= Open(filename
, MODE_NEWFILE
);
6431 Write(filehandle
, buf
, (AROS_LONG2BE(buf
[1])+9) & ~1UL);
6435 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
),
6436 "Failed to write config to '%s'!",
6441 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6444 ps
->ps_SavedConfigHash
= ps
->ps_ConfigHash
;
6451 /* /// "psdWriteCfg()" */
6452 AROS_LH1(APTR
, psdWriteCfg
,
6453 AROS_LHA(struct PsdIFFContext
*, pic
, A0
),
6454 LIBBASETYPEPTR
, ps
, 53, psd
)
6460 KPRINTF(10, ("psdWriteCfg(%p)\n", pic
));
6462 pLockSemShared(ps
, &ps
->ps_ConfigLock
);
6465 pic
= (struct PsdIFFContext
*) ps
->ps_ConfigRoot
.lh_Head
;
6466 if(!(pic
->pic_Node
.ln_Succ
))
6468 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6472 pUpdateGlobalCfg(ps
, pic
);
6473 ps
->ps_CheckConfigReq
= TRUE
;
6474 len
= pGetFormLength(pic
);
6475 if((buf
= psdAllocVec(len
)))
6477 pInternalWriteForm(pic
, buf
);
6479 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6485 /* /// "psdFindCfgForm()" */
6486 AROS_LH2(struct PsdIFFContext
*, psdFindCfgForm
,
6487 AROS_LHA(struct PsdIFFContext
*, pic
, A0
),
6488 AROS_LHA(ULONG
, formid
, D0
),
6489 LIBBASETYPEPTR
, ps
, 54, psd
)
6492 struct PsdIFFContext
*subpic
;
6494 KPRINTF(160, ("psdFindCfgForm(0x%p, 0x%08lx)\n", pic
, formid
));
6495 pLockSemShared(ps
, &ps
->ps_ConfigLock
);
6498 pic
= (struct PsdIFFContext
*) ps
->ps_ConfigRoot
.lh_Head
;
6499 if(!(pic
->pic_Node
.ln_Succ
))
6501 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6505 subpic
= (struct PsdIFFContext
*) pic
->pic_SubForms
.lh_Head
;
6506 while(subpic
->pic_Node
.ln_Succ
)
6508 if(subpic
->pic_FormID
== formid
)
6510 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6513 subpic
= (struct PsdIFFContext
*) subpic
->pic_Node
.ln_Succ
;
6515 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6521 /* /// "psdNextCfgForm()" */
6522 AROS_LH1(struct PsdIFFContext
*, psdNextCfgForm
,
6523 AROS_LHA(struct PsdIFFContext
*, pic
, A0
),
6524 LIBBASETYPEPTR
, ps
, 55, psd
)
6528 KPRINTF(160, ("psdNextCfgForm(%p)\n", pic
));
6534 pLockSemShared(ps
, &ps
->ps_ConfigLock
);
6535 formid
= pic
->pic_FormID
;
6536 pic
= (struct PsdIFFContext
*) pic
->pic_Node
.ln_Succ
;
6537 while(pic
->pic_Node
.ln_Succ
)
6539 if(pic
->pic_FormID
== formid
)
6541 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6543 KPRINTF(1, ("Found context 0x%p\n", pic
));
6546 pic
= (struct PsdIFFContext
*) pic
->pic_Node
.ln_Succ
;
6548 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6554 /* /// "psdAllocCfgForm()" */
6555 AROS_LH1(struct PsdIFFContext
*, psdAllocCfgForm
,
6556 AROS_LHA(ULONG
, formid
, D0
),
6557 LIBBASETYPEPTR
, ps
, 86, psd
)
6560 struct PsdIFFContext
*pic
;
6561 KPRINTF(10, ("psdAllocCfgForm(%p)\n", formid
));
6562 if((pic
= psdAllocVec(sizeof(struct PsdIFFContext
))))
6564 NewList(&pic
->pic_SubForms
);
6565 //pic->pic_Parent = parent;
6566 pic
->pic_FormID
= formid
;
6567 pic
->pic_FormLength
= 4;
6568 pic
->pic_Chunks
= NULL
;
6569 pic
->pic_ChunksLen
= 0;
6570 pic
->pic_BufferLen
= 0;
6572 AddTail(&ps
->ps_AlienConfigs
, &pic
->pic_Node
);
6580 /* /// "psdRemCfgForm()" */
6581 AROS_LH1(void, psdRemCfgForm
,
6582 AROS_LHA(struct PsdIFFContext
*, pic
, A0
),
6583 LIBBASETYPEPTR
, ps
, 56, psd
)
6586 KPRINTF(10, ("psdRemCfgForm(%p)\n", pic
));
6588 pLockSemExcl(ps
, &ps
->ps_ConfigLock
);
6591 pic
= (struct PsdIFFContext
*) ps
->ps_ConfigRoot
.lh_Head
;
6592 if(!(pic
->pic_Node
.ln_Succ
))
6594 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6599 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6600 ps
->ps_CheckConfigReq
= TRUE
;
6605 /* /// "psdAddCfgEntry()" */
6606 AROS_LH2(struct PsdIFFContext
*, psdAddCfgEntry
,
6607 AROS_LHA(struct PsdIFFContext
*, pic
, A0
),
6608 AROS_LHA(APTR
, formdata
, A1
),
6609 LIBBASETYPEPTR
, ps
, 57, psd
)
6612 struct PsdIFFContext
*res
;
6614 KPRINTF(10, ("psdAddCfgEntry(%p, %p)\n", pic
, formdata
));
6615 pLockSemExcl(ps
, &ps
->ps_ConfigLock
);
6618 pic
= (struct PsdIFFContext
*) ps
->ps_ConfigRoot
.lh_Head
;
6619 if(!(pic
->pic_Node
.ln_Succ
))
6621 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6625 res
= pAddCfgChunk(ps
, pic
, formdata
);
6626 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6627 ps
->ps_CheckConfigReq
= TRUE
;
6633 /* /// "psdRemCfgChunk()" */
6634 AROS_LH2(BOOL
, psdRemCfgChunk
,
6635 AROS_LHA(struct PsdIFFContext
*, pic
, A0
),
6636 AROS_LHA(ULONG
, chnkid
, D0
),
6637 LIBBASETYPEPTR
, ps
, 58, psd
)
6642 KPRINTF(10, ("psdRemCfgChunk(%p, %p)\n", pic
, chnkid
));
6643 pLockSemExcl(ps
, &ps
->ps_ConfigLock
);
6646 pic
= (struct PsdIFFContext
*) ps
->ps_ConfigRoot
.lh_Head
;
6647 if(!(pic
->pic_Node
.ln_Succ
))
6649 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6655 res
= pRemCfgChunk(ps
, pic
, chnkid
);
6657 struct PsdIFFContext
*subpic
= (struct PsdIFFContext
*) pic
->pic_SubForms
.lh_Head
;
6658 while(subpic
->pic_Node
.ln_Succ
)
6660 pFreeForm(ps
, subpic
);
6662 subpic
= (struct PsdIFFContext
*) pic
->pic_SubForms
.lh_Head
;
6664 if(pic
->pic_ChunksLen
)
6668 pic
->pic_ChunksLen
= 0;
6669 pic
->pic_FormLength
= 4;
6672 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6673 ps
->ps_CheckConfigReq
= TRUE
;
6679 /* /// "psdGetCfgChunk()" */
6680 AROS_LH2(APTR
, psdGetCfgChunk
,
6681 AROS_LHA(struct PsdIFFContext
*, pic
, A0
),
6682 AROS_LHA(ULONG
, chnkid
, D0
),
6683 LIBBASETYPEPTR
, ps
, 59, psd
)
6689 KPRINTF(10, ("psdGetCfgChunk(%p, 0x%08lx)\n", pic
, chnkid
));
6691 pLockSemShared(ps
, &ps
->ps_ConfigLock
);
6694 pic
= (struct PsdIFFContext
*) ps
->ps_ConfigRoot
.lh_Head
;
6695 if(!(pic
->pic_Node
.ln_Succ
))
6697 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6701 pUpdateGlobalCfg(ps
, pic
);
6702 chnk
= pFindCfgChunk(ps
, pic
, chnkid
);
6705 res
= psdAllocVec(AROS_LONG2BE(chnk
[1])+8);
6708 memcpy(res
, chnk
, AROS_LONG2BE(chnk
[1])+8);
6711 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6717 /* /// "psdParseCfg()" */
6718 AROS_LH0(void, psdParseCfg
,
6719 LIBBASETYPEPTR
, ps
, 60, psd
)
6722 struct PsdIFFContext
*pic
;
6723 struct PsdIFFContext
*subpic
;
6727 struct PsdHardware
*phw
;
6728 struct PsdUsbClass
*puc
;
6729 BOOL removeall
= TRUE
;
6730 BOOL nodos
= (FindTask(NULL
)->tc_Node
.ln_Type
!= NT_PROCESS
);
6733 XPRINTF(10, ("psdParseCfg()\n"));
6735 pLockSemShared(ps
, &ps
->ps_ConfigLock
);
6736 pCheckCfgChanged(ps
);
6737 pic
= psdFindCfgForm(NULL
, IFFFORM_STACKCFG
);
6740 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6744 // if no config for hardware is found, we don't remove the devices,
6745 // because this could render the system useless (no USB mice or
6746 // keyboards to configure the hardware!)
6747 if(!psdFindCfgForm(pic
, IFFFORM_UHWDEVICE
))
6749 XPRINTF(10, ("No hardware data present\n"));
6755 /* select all hardware devices for removal */
6756 phw
= (struct PsdHardware
*) ps
->ps_Hardware
.lh_Head
;
6757 while(phw
->phw_Node
.ln_Succ
)
6759 phw
->phw_RemoveMe
= removeall
;
6760 phw
= (struct PsdHardware
*) phw
->phw_Node
.ln_Succ
;
6763 /* select all classes for removal */
6764 puc
= (struct PsdUsbClass
*) ps
->ps_Classes
.lh_Head
;
6765 while(puc
->puc_Node
.ln_Succ
)
6768 * For kickstart-resident classes we check usage count, and
6769 * remove them only if it's zero.
6770 * These classes can be responsible for devices which we can use
6771 * at boot time. If we happen to remove them, we can end up with
6772 * no input or storage devices at all.
6774 if (FindResident(puc
->puc_ClassName
))
6775 puc
->puc_RemoveMe
= (puc
->puc_UseCnt
== 0);
6777 puc
->puc_RemoveMe
= TRUE
;
6779 puc
= (struct PsdUsbClass
*) puc
->puc_Node
.ln_Succ
;
6784 /* Get Hardware config */
6785 subpic
= psdFindCfgForm(pic
, IFFFORM_UHWDEVICE
);
6788 chnk
= pFindCfgChunk(ps
, subpic
, IFFCHNK_NAME
);
6791 name
= (STRPTR
) &chnk
[2];
6793 chnk
= pFindCfgChunk(ps
, subpic
, IFFCHNK_UNIT
);
6798 if(!pFindCfgChunk(ps
, subpic
, IFFCHNK_OFFLINE
))
6800 phw
= pFindHardware(ps
, name
, unit
);
6801 XPRINTF(5, ("Have configuration for device 0x%p (%s unit %u)\n", phw
, name
, unit
));
6804 phw
->phw_RemoveMe
= FALSE
;
6808 subpic
= psdNextCfgForm(subpic
);
6811 /* Get Class config */
6812 subpic
= psdFindCfgForm(pic
, IFFFORM_USBCLASS
);
6815 chnk
= pFindCfgChunk(ps
, subpic
, IFFCHNK_NAME
);
6818 name
= (STRPTR
) &chnk
[2];
6819 puc
= (struct PsdUsbClass
*) pFindName(ps
, &ps
->ps_Classes
, name
);
6820 XPRINTF(5, ("Have configuration for class 0x%p (%s)\n", puc
, name
));
6823 puc
->puc_RemoveMe
= FALSE
;
6826 subpic
= psdNextCfgForm(subpic
);
6829 // unlock config while removing to avoid deadlocks.
6830 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6832 /* now remove remaining classes not found in the config */
6833 puc
= (struct PsdUsbClass
*) ps
->ps_Classes
.lh_Head
;
6834 while(puc
->puc_Node
.ln_Succ
)
6836 if(puc
->puc_RemoveMe
)
6838 XPRINTF(5, ("Removing class %s\n", puc
->puc_ClassName
));
6840 puc
= (struct PsdUsbClass
*) ps
->ps_Classes
.lh_Head
;
6842 puc
= (struct PsdUsbClass
*) puc
->puc_Node
.ln_Succ
;
6846 /* now remove all remaining hardware not found in the config */
6847 phw
= (struct PsdHardware
*) ps
->ps_Hardware
.lh_Head
;
6848 while(phw
->phw_Node
.ln_Succ
)
6850 if(phw
->phw_RemoveMe
)
6852 XPRINTF(5, ("Removing device %s unit %u\n", phw
->phw_DevName
, phw
->phw_Unit
));
6853 psdRemHardware(phw
);
6854 phw
= (struct PsdHardware
*) ps
->ps_Hardware
.lh_Head
;
6856 phw
= (struct PsdHardware
*) phw
->phw_Node
.ln_Succ
;
6860 pLockSemShared(ps
, &ps
->ps_ConfigLock
);
6861 pic
= psdFindCfgForm(NULL
, IFFFORM_STACKCFG
);
6864 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6869 /* Add missing Classes */
6870 subpic
= psdFindCfgForm(pic
, IFFFORM_USBCLASS
);
6873 chnk
= pFindCfgChunk(ps
, subpic
, IFFCHNK_NAME
);
6876 /* *** FIXME *** POSSIBLE DEADLOCK WHEN CLASS TRIES TO DO CONFIG STUFF IN
6877 AN EXTERNAL TASK INSIDE LIBOPEN CODE */
6878 name
= (STRPTR
) &chnk
[2];
6879 puc
= (struct PsdUsbClass
*) pFindName(ps
, &ps
->ps_Classes
, name
);
6882 psdAddClass(name
, 0);
6885 subpic
= psdNextCfgForm(subpic
);
6888 /* Now really mount Hardware found in config */
6889 subpic
= psdFindCfgForm(pic
, IFFFORM_UHWDEVICE
);
6892 chnk
= pFindCfgChunk(ps
, subpic
, IFFCHNK_NAME
);
6895 name
= (STRPTR
) &chnk
[2];
6897 chnk
= pFindCfgChunk(ps
, subpic
, IFFCHNK_UNIT
);
6902 if(!pFindCfgChunk(ps
, subpic
, IFFCHNK_OFFLINE
))
6904 phw
= pFindHardware(ps
, name
, unit
);
6907 phw
= psdAddHardware(name
, unit
);
6910 psdEnumerateHardware(phw
);
6915 subpic
= psdNextCfgForm(subpic
);
6917 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
6919 if(!nodos
&& ps
->ps_StartedAsTask
)
6921 // last time we were reading the config before DOS, so maybe we need to
6922 // unbind some classes that need to be overruled by newly available classes,
6923 // such as hid.class overruling bootmouse & bootkeyboard.
6924 // so unbind those classes that promote themselves as AfterDOS
6927 psdAddErrorMsg0(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
), "Checking AfterDOS...");
6928 puc
= (struct PsdUsbClass
*) ps
->ps_Classes
.lh_Head
;
6929 while(puc
->puc_Node
.ln_Succ
)
6932 usbGetAttrs(UGA_CLASS
, NULL
,
6933 UCCA_AfterDOSRestart
, &restartme
,
6936 if(restartme
&& puc
->puc_UseCnt
)
6938 struct PsdDevice
*pd
;
6939 struct PsdConfig
*pc
;
6940 struct PsdInterface
*pif
;
6942 /* Well, try to release the open bindings in a best effort attempt */
6944 while((pd
= psdGetNextDevice(pd
)))
6946 if(pd
->pd_DevBinding
&& (pd
->pd_ClsBinding
== puc
) && (!(pd
->pd_Flags
& PDFF_APPBINDING
)))
6949 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
6950 "AfterDOS: Temporarily releasing %s %s binding to %s.",
6951 puc
->puc_ClassName
, "device", pd
->pd_ProductStr
);
6952 psdReleaseDevBinding(pd
);
6954 pd
= NULL
; /* restart */
6957 pc
= (struct PsdConfig
*) pd
->pd_Configs
.lh_Head
;
6958 while(pc
->pc_Node
.ln_Succ
)
6960 pif
= (struct PsdInterface
*) pc
->pc_Interfaces
.lh_Head
;
6961 while(pif
->pif_Node
.ln_Succ
)
6963 if(pif
->pif_IfBinding
&& (pif
->pif_ClsBinding
== puc
))
6966 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
6967 "AfterDOS: Temporarily releasing %s %s binding to %s.",
6968 puc
->puc_ClassName
, "interface", pd
->pd_ProductStr
);
6969 psdReleaseIfBinding(pif
);
6971 pd
= NULL
; /* restart */
6974 pif
= (struct PsdInterface
*) pif
->pif_Node
.ln_Succ
;
6976 pc
= (struct PsdConfig
*) pc
->pc_Node
.ln_Succ
;
6980 usbDoMethodA(UCM_DOSAvailableEvent
, NULL
);
6981 puc
= (struct PsdUsbClass
*) puc
->puc_Node
.ln_Succ
;
6983 ps
->ps_StartedAsTask
= FALSE
;
6987 if(nodos
&& (!ps
->ps_ConfigRead
))
6989 // it's the first time we were reading the config and DOS was not available
6990 ps
->ps_StartedAsTask
= TRUE
;
6992 ps
->ps_ConfigRead
= TRUE
;
6993 ps
->ps_SavedConfigHash
= ps
->ps_ConfigHash
; // update saved hash
6995 /* do a class scan */
6998 if(nodos
&& ps
->ps_GlobalCfg
->pgc_BootDelay
)
7000 // wait for hubs to settle
7002 puc
= (struct PsdUsbClass
*) FindName(&ps
->ps_Classes
, "massstorage.class");
7003 if(puc
&& puc
->puc_UseCnt
)
7005 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
7006 "Delaying further execution by %ld second(s) (boot delay).",
7007 ps
->ps_GlobalCfg
->pgc_BootDelay
);
7008 if(ps
->ps_GlobalCfg
->pgc_BootDelay
>= 1);
7010 psdDelayMS((ps
->ps_GlobalCfg
->pgc_BootDelay
-1)*1000);
7013 psdAddErrorMsg0(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
), "Boot delay skipped, no mass storage devices found.");
7020 /* /// "psdSetClsCfg()" */
7021 AROS_LH2(BOOL
, psdSetClsCfg
,
7022 AROS_LHA(STRPTR
, owner
, A0
),
7023 AROS_LHA(APTR
, form
, A1
),
7024 LIBBASETYPEPTR
, ps
, 62, psd
)
7027 struct PsdIFFContext
*pic
;
7028 BOOL result
= FALSE
;
7030 KPRINTF(10, ("psdSetClsCfg(%s, %p)\n", owner
, form
));
7031 pLockSemExcl(ps
, &ps
->ps_ConfigLock
);
7032 pic
= psdFindCfgForm(NULL
, IFFFORM_CLASSCFG
);
7035 if(pMatchStringChunk(ps
, pic
, IFFCHNK_OWNER
, owner
))
7037 pic
= psdFindCfgForm(pic
, IFFFORM_CLASSDATA
);
7042 result
= psdReadCfg(pic
, form
);
7044 psdRemCfgChunk(pic
, 0);
7052 pic
= psdNextCfgForm(pic
);
7056 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
7057 pCheckCfgChanged(ps
);
7060 pic
= (struct PsdIFFContext
*) ps
->ps_ConfigRoot
.lh_Head
;
7061 if(pic
->pic_Node
.ln_Succ
)
7063 pic
= pAllocForm(ps
, pic
, IFFFORM_CLASSCFG
);
7066 if(pAddStringChunk(ps
, pic
, IFFCHNK_OWNER
, owner
))
7070 if(pAddCfgChunk(ps
, pic
, form
))
7072 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
7073 pCheckCfgChanged(ps
);
7078 buf
[0] = AROS_LONG2BE(ID_FORM
);
7079 buf
[1] = AROS_LONG2BE(4);
7080 buf
[2] = AROS_LONG2BE(IFFFORM_CLASSDATA
);
7081 if(pAddCfgChunk(ps
, pic
, buf
))
7083 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
7084 pCheckCfgChanged(ps
);
7091 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
7092 pCheckCfgChanged(ps
);
7098 /* /// "psdGetClsCfg()" */
7099 AROS_LH1(struct PsdIFFContext
*, psdGetClsCfg
,
7100 AROS_LHA(STRPTR
, owner
, A0
),
7101 LIBBASETYPEPTR
, ps
, 63, psd
)
7104 struct PsdIFFContext
*pic
;
7106 KPRINTF(10, ("psdGetClsCfg(%s)\n", owner
));
7107 pic
= psdFindCfgForm(NULL
, IFFFORM_CLASSCFG
);
7110 if(pMatchStringChunk(ps
, pic
, IFFCHNK_OWNER
, owner
))
7112 return(psdFindCfgForm(pic
, IFFFORM_CLASSDATA
));
7114 pic
= psdNextCfgForm(pic
);
7121 /* /// "psdSetUsbDevCfg()" */
7122 AROS_LH4(BOOL
, psdSetUsbDevCfg
,
7123 AROS_LHA(STRPTR
, owner
, A0
),
7124 AROS_LHA(STRPTR
, devid
, A2
),
7125 AROS_LHA(STRPTR
, ifid
, A3
),
7126 AROS_LHA(APTR
, form
, A1
),
7127 LIBBASETYPEPTR
, ps
, 64, psd
)
7130 struct PsdIFFContext
*pic
;
7131 struct PsdIFFContext
*cpic
= NULL
;
7132 struct PsdIFFContext
*mpic
= NULL
;
7133 BOOL result
= FALSE
;
7135 KPRINTF(10, ("psdSetUsbDevCfg(%s, %s, %s, %p)\n", owner
, devid
, ifid
, form
));
7136 pLockSemExcl(ps
, &ps
->ps_ConfigLock
);
7137 /* Find device config form. It contains all device config data */
7138 pic
= psdFindCfgForm(NULL
, IFFFORM_DEVICECFG
);
7141 /* Find DEVID-Chunk. Check if it matches our device id */
7142 if(pMatchStringChunk(ps
, pic
, IFFCHNK_DEVID
, devid
))
7145 /* We found the correct device. Now if we need to store interface data, find the interface first */
7148 /* Search interface config form */
7149 mpic
= psdFindCfgForm(pic
, IFFFORM_IFCFGDATA
);
7152 /* Found the form. Find the the ID String for the interface */
7153 if(pMatchStringChunk(ps
, mpic
, IFFCHNK_IFID
, ifid
))
7155 /* ID did match, now check for owner */
7156 if(pMatchStringChunk(ps
, mpic
, IFFCHNK_OWNER
, owner
))
7158 /* found it! So there is already a config saved in there. Search for dev config data form */
7159 cpic
= psdFindCfgForm(mpic
, IFFFORM_IFCLSDATA
);
7162 /* not found, generate it */
7163 cpic
= pAllocForm(ps
, mpic
, IFFFORM_IFCLSDATA
);
7168 mpic
= psdNextCfgForm(mpic
);
7172 if((mpic
= pAllocForm(ps
, pic
, IFFFORM_IFCFGDATA
)))
7174 if(pAddStringChunk(ps
, mpic
, IFFCHNK_OWNER
, owner
))
7176 if(pAddStringChunk(ps
, mpic
, IFFCHNK_IFID
, ifid
))
7178 cpic
= pAllocForm(ps
, mpic
, IFFFORM_IFCLSDATA
);
7184 /* Search for device config */
7185 mpic
= psdFindCfgForm(pic
, IFFFORM_DEVCFGDATA
);
7188 /* search for the right owner */
7189 if(pMatchStringChunk(ps
, mpic
, IFFCHNK_OWNER
, owner
))
7191 /* found it! So there is already a config saved in there. Search for dev config data form */
7192 cpic
= psdFindCfgForm(mpic
, IFFFORM_DEVCLSDATA
);
7195 /* not found, generate it */
7196 cpic
= pAllocForm(ps
, mpic
, IFFFORM_DEVCLSDATA
);
7200 mpic
= psdNextCfgForm(mpic
);
7202 if(!cpic
) /* no device config form */
7204 if((mpic
= pAllocForm(ps
, pic
, IFFFORM_DEVCFGDATA
)))
7206 if(pAddStringChunk(ps
, mpic
, IFFCHNK_OWNER
, owner
))
7208 cpic
= pAllocForm(ps
, mpic
, IFFFORM_DEVCLSDATA
);
7217 result
= psdReadCfg(cpic
, form
);
7219 psdRemCfgChunk(cpic
, 0);
7225 pic
= psdNextCfgForm(pic
);
7229 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
7230 pCheckCfgChanged(ps
);
7234 pic
= (struct PsdIFFContext
*) ps
->ps_ConfigRoot
.lh_Head
;
7235 if(pic
->pic_Node
.ln_Succ
)
7237 pic
= pAllocForm(ps
, pic
, IFFFORM_DEVICECFG
);
7240 if(pAddStringChunk(ps
, pic
, IFFCHNK_DEVID
, devid
))
7244 if((mpic
= pAllocForm(ps
, pic
, IFFFORM_IFCFGDATA
)))
7246 if(pAddStringChunk(ps
, mpic
, IFFCHNK_OWNER
, owner
))
7248 if(pAddStringChunk(ps
, mpic
, IFFCHNK_IFID
, ifid
))
7250 cpic
= pAllocForm(ps
, mpic
, IFFFORM_IFCLSDATA
);
7255 if((mpic
= pAllocForm(ps
, pic
, IFFFORM_DEVCFGDATA
)))
7257 if(pAddStringChunk(ps
, mpic
, IFFCHNK_OWNER
, owner
))
7259 cpic
= pAllocForm(ps
, mpic
, IFFFORM_DEVCLSDATA
);
7267 result
= psdReadCfg(cpic
, form
);
7269 psdRemCfgChunk(cpic
, 0);
7276 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
7277 pCheckCfgChanged(ps
);
7283 /* /// "psdGetUsbDevCfg()" */
7284 AROS_LH3(struct PsdIFFContext
*, psdGetUsbDevCfg
,
7285 AROS_LHA(STRPTR
, owner
, A0
),
7286 AROS_LHA(STRPTR
, devid
, A2
),
7287 AROS_LHA(STRPTR
, ifid
, A3
),
7288 LIBBASETYPEPTR
, ps
, 65, psd
)
7291 struct PsdIFFContext
*pic
;
7292 struct PsdIFFContext
*cpic
= NULL
;
7293 struct PsdIFFContext
*mpic
= NULL
;
7295 KPRINTF(10, ("psdGetUsbDevCfg(%s, %s, %s)\n", owner
, devid
, ifid
));
7296 pLockSemShared(ps
, &ps
->ps_ConfigLock
);
7297 /* Find device config form. It contains all device config data */
7298 pic
= psdFindCfgForm(NULL
, IFFFORM_DEVICECFG
);
7301 /* Find DEVID-Chunk. Check if it matches our device id */
7302 if(pMatchStringChunk(ps
, pic
, IFFCHNK_DEVID
, devid
))
7305 /* We found the correct device. Now if we need to store interface data, find the interface first */
7308 /* Search interface config form */
7309 mpic
= psdFindCfgForm(pic
, IFFFORM_IFCFGDATA
);
7312 /* Found the form. Find the the ID String for the interface */
7313 if(pMatchStringChunk(ps
, mpic
, IFFCHNK_IFID
, ifid
))
7315 /* ID did match, now check for owner */
7316 if(pMatchStringChunk(ps
, mpic
, IFFCHNK_OWNER
, owner
))
7318 /* found it! So there is already a config saved in there. Search for dev config data form */
7319 cpic
= psdFindCfgForm(mpic
, IFFFORM_IFCLSDATA
);
7323 mpic
= psdNextCfgForm(mpic
);
7326 /* Search for device config */
7327 mpic
= psdFindCfgForm(pic
, IFFFORM_DEVCFGDATA
);
7330 /* search for the right owner */
7331 if(pMatchStringChunk(ps
, mpic
, IFFCHNK_OWNER
, owner
))
7333 /* found it! So there is already a config saved in there. Search for dev config data form */
7334 cpic
= psdFindCfgForm(mpic
, IFFFORM_DEVCLSDATA
);
7337 mpic
= psdNextCfgForm(mpic
);
7342 pic
= psdNextCfgForm(pic
);
7344 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
7345 KPRINTF(1, ("Result %p\n", cpic
));
7351 /* /// "psdSetForcedBinding()" */
7352 AROS_LH3(BOOL
, psdSetForcedBinding
,
7353 AROS_LHA(STRPTR
, owner
, A2
),
7354 AROS_LHA(STRPTR
, devid
, A0
),
7355 AROS_LHA(STRPTR
, ifid
, A1
),
7356 LIBBASETYPEPTR
, ps
, 69, psd
)
7359 struct PsdIFFContext
*pic
;
7360 struct PsdIFFContext
*mpic
= NULL
;
7362 BOOL result
= FALSE
;
7366 olen
= strlen(owner
);
7368 pLockSemExcl(ps
, &ps
->ps_ConfigLock
);
7369 /* Find device config form. It contains all device config data */
7370 pic
= psdFindCfgForm(NULL
, IFFFORM_DEVICECFG
);
7373 /* Find DEVID-Chunk. Check if it matches our device id */
7374 if(pMatchStringChunk(ps
, pic
, IFFCHNK_DEVID
, devid
))
7376 /* We found the correct device. Now if we need to store interface data, find the interface first */
7379 /* Search interface config form */
7380 mpic
= psdFindCfgForm(pic
, IFFFORM_IFCFGDATA
);
7383 /* Found the form. Find the the ID String for the interface */
7384 if(pMatchStringChunk(ps
, mpic
, IFFCHNK_IFID
, ifid
))
7386 /* ID did match, insert/replace forced binding */
7389 if(pAddStringChunk(ps
, mpic
, IFFCHNK_FORCEDBIND
, owner
))
7394 pRemCfgChunk(ps
, mpic
, IFFCHNK_FORCEDBIND
);
7398 mpic
= psdNextCfgForm(mpic
);
7404 if((!result
) && olen
)
7406 if((mpic
= pAllocForm(ps
, pic
, IFFFORM_IFCFGDATA
)))
7408 if(pAddStringChunk(ps
, mpic
, IFFCHNK_OWNER
, owner
))
7410 if(pAddStringChunk(ps
, mpic
, IFFCHNK_FORCEDBIND
, owner
))
7412 if(pAddStringChunk(ps
, mpic
, IFFCHNK_IFID
, ifid
))
7421 /* Add FBND chunk */
7424 if(pAddStringChunk(ps
, pic
, IFFCHNK_FORCEDBIND
, owner
))
7429 pRemCfgChunk(ps
, pic
, IFFCHNK_FORCEDBIND
);
7435 pic
= psdNextCfgForm(pic
);
7443 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
7444 pCheckCfgChanged(ps
);
7447 pic
= (struct PsdIFFContext
*) ps
->ps_ConfigRoot
.lh_Head
;
7448 if(pic
->pic_Node
.ln_Succ
)
7450 pic
= pAllocForm(ps
, pic
, IFFFORM_DEVICECFG
);
7453 if(pAddStringChunk(ps
, pic
, IFFCHNK_DEVID
, devid
))
7457 if((mpic
= pAllocForm(ps
, pic
, IFFFORM_IFCFGDATA
)))
7459 if(pAddStringChunk(ps
, mpic
, IFFCHNK_OWNER
, owner
))
7461 if(pAddStringChunk(ps
, mpic
, IFFCHNK_FORCEDBIND
, owner
))
7463 if(pAddStringChunk(ps
, mpic
, IFFCHNK_IFID
, ifid
))
7471 /* Add FBND chunk */
7472 if(pAddStringChunk(ps
, pic
, IFFCHNK_FORCEDBIND
, owner
))
7480 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
7481 pCheckCfgChanged(ps
);
7487 /* /// "psdGetForcedBinding()" */
7488 AROS_LH2(STRPTR
, psdGetForcedBinding
,
7489 AROS_LHA(STRPTR
, devid
, A0
),
7490 AROS_LHA(STRPTR
, ifid
, A1
),
7491 LIBBASETYPEPTR
, ps
, 70, psd
)
7494 struct PsdIFFContext
*pic
;
7495 struct PsdIFFContext
*mpic
= NULL
;
7497 STRPTR owner
= NULL
;
7499 pLockSemShared(ps
, &ps
->ps_ConfigLock
);
7500 /* Find device config form. It contains all device config data */
7501 pic
= psdFindCfgForm(NULL
, IFFFORM_DEVICECFG
);
7504 /* Find DEVID-Chunk. Check if it matches our device id */
7505 if(pMatchStringChunk(ps
, pic
, IFFCHNK_DEVID
, devid
))
7507 /* We found the correct device. Now if we need to store interface data, find the interface first */
7510 /* Search interface config form */
7511 mpic
= psdFindCfgForm(pic
, IFFFORM_IFCFGDATA
);
7514 /* Found the form. Find the the ID String for the interface */
7515 if(pMatchStringChunk(ps
, mpic
, IFFCHNK_IFID
, ifid
))
7517 /* ID did match, now check for forced binding */
7518 chunk
= pFindCfgChunk(ps
, mpic
, IFFCHNK_FORCEDBIND
);
7521 owner
= (STRPTR
) &chunk
[2];
7525 mpic
= psdNextCfgForm(mpic
);
7528 /* Search for device forced binding */
7529 chunk
= pFindCfgChunk(ps
, pic
, IFFCHNK_FORCEDBIND
);
7532 owner
= (STRPTR
) &chunk
[2];
7538 pic
= psdNextCfgForm(pic
);
7540 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
7546 /* /// "psdAddStringChunk()" */
7547 AROS_LH3(BOOL
, psdAddStringChunk
,
7548 AROS_LHA(struct PsdIFFContext
*, pic
, A0
),
7549 AROS_LHA(ULONG
, chunkid
, D0
),
7550 AROS_LHA(CONST_STRPTR
, str
, A1
),
7551 LIBBASETYPEPTR
, ps
, 87, psd
)
7555 KPRINTF(10, ("psdAddStringChunk(%p, %p, %s)\n", pic
, chunkid
, str
));
7556 pLockSemExcl(ps
, &ps
->ps_ConfigLock
);
7557 res
= pAddStringChunk(ps
, pic
, chunkid
, str
);
7558 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
7564 /* /// "psdMatchStringChunk()" */
7565 AROS_LH3(BOOL
, psdMatchStringChunk
,
7566 AROS_LHA(struct PsdIFFContext
*, pic
, A0
),
7567 AROS_LHA(ULONG
, chunkid
, D0
),
7568 AROS_LHA(CONST_STRPTR
, str
, A1
),
7569 LIBBASETYPEPTR
, ps
, 88, psd
)
7573 KPRINTF(10, ("psdMatchStringChunk(%p, %p, %s)\n", pic
, chunkid
, str
));
7574 pLockSemShared(ps
, &ps
->ps_ConfigLock
);
7575 res
= pMatchStringChunk(ps
, pic
, chunkid
, str
);
7576 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
7582 /* /// "psdGetStringChunk()" */
7583 AROS_LH2(STRPTR
, psdGetStringChunk
,
7584 AROS_LHA(struct PsdIFFContext
*, pic
, A0
),
7585 AROS_LHA(ULONG
, chunkid
, D0
),
7586 LIBBASETYPEPTR
, ps
, 89, psd
)
7590 KPRINTF(10, ("psdGetStringChunk(%p, %p)\n", pic
, chunkid
));
7591 pLockSemShared(ps
, &ps
->ps_ConfigLock
);
7592 str
= pGetStringChunk(ps
, pic
, chunkid
);
7593 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
7599 /* *** Configuration (non-library subroutines) *** */
7601 /* /// "pAllocForm()" */
7602 struct PsdIFFContext
* pAllocForm(LIBBASETYPEPTR ps
, struct PsdIFFContext
*parent
, ULONG formid
)
7604 struct PsdIFFContext
*pic
;
7605 KPRINTF(10, ("pAllocForm(%p, %p)\n", parent
, formid
));
7606 if((pic
= psdAllocVec(sizeof(struct PsdIFFContext
))))
7608 NewList(&pic
->pic_SubForms
);
7609 //pic->pic_Parent = parent;
7610 pic
->pic_FormID
= formid
;
7611 pic
->pic_FormLength
= 4;
7612 pic
->pic_Chunks
= NULL
;
7613 pic
->pic_ChunksLen
= 0;
7614 pic
->pic_BufferLen
= 0;
7618 AddTail(&parent
->pic_SubForms
, &pic
->pic_Node
);
7620 AddTail(&ps
->ps_ConfigRoot
, &pic
->pic_Node
);
7628 /* /// "pFreeForm()" */
7629 void pFreeForm(LIBBASETYPEPTR ps
, struct PsdIFFContext
*pic
)
7631 struct PsdIFFContext
*subpic
= (struct PsdIFFContext
*) pic
->pic_SubForms
.lh_Head
;
7632 KPRINTF(10, ("pFreeForm(%p)\n", pic
));
7633 Remove(&pic
->pic_Node
);
7634 while(subpic
->pic_Node
.ln_Succ
)
7636 pFreeForm(ps
, subpic
);
7637 subpic
= (struct PsdIFFContext
*) pic
->pic_SubForms
.lh_Head
;
7639 psdFreeVec(pic
->pic_Chunks
);
7644 /* /// "pGetFormLength()" */
7645 ULONG
pGetFormLength(struct PsdIFFContext
*pic
)
7647 ULONG len
= (5 + pic
->pic_ChunksLen
) & ~1UL;
7648 struct PsdIFFContext
*subpic
= (struct PsdIFFContext
*) pic
->pic_SubForms
.lh_Head
;
7649 //KPRINTF(10, ("pGetFormLength(%p)\n", pic));
7650 while(subpic
->pic_Node
.ln_Succ
)
7652 len
+= pGetFormLength(subpic
);
7653 subpic
= (struct PsdIFFContext
*) subpic
->pic_Node
.ln_Succ
;
7655 pic
->pic_FormLength
= len
;
7656 //KPRINTF(10, ("FormLen=%ld\n", len+8));
7661 /* /// "pFindCfgChunk()" */
7662 APTR
pFindCfgChunk(LIBBASETYPEPTR ps
, struct PsdIFFContext
*pic
, ULONG chnkid
)
7664 ULONG
*buf
= pic
->pic_Chunks
;
7665 ULONG len
= pic
->pic_ChunksLen
;
7667 KPRINTF(10, ("pFindCfgChunk(%p, %p)\n", pic
, chnkid
));
7671 if(AROS_LONG2BE(*buf
) == chnkid
)
7673 KPRINTF(10, ("Found at %p\n", buf
));
7676 chlen
= (AROS_LONG2BE(buf
[1]) + 9) & ~1UL;
7678 buf
= (ULONG
*) (((UBYTE
*) buf
) + chlen
);
7680 KPRINTF(10, ("Not found!\n"));
7685 /* /// "pRemCfgChunk()" */
7686 BOOL
pRemCfgChunk(LIBBASETYPEPTR ps
, struct PsdIFFContext
*pic
, ULONG chnkid
)
7688 ULONG
*buf
= pic
->pic_Chunks
;
7689 ULONG len
= pic
->pic_ChunksLen
;
7691 KPRINTF(10, ("pRemCfgChunk(%p, %p)\n", pic
, chnkid
));
7695 chlen
= ((AROS_LONG2BE(buf
[1])) + 9) & ~1UL;
7696 if(AROS_LONG2BE(*buf
) == chnkid
)
7701 memcpy(buf
, &((UBYTE
*) buf
)[chlen
], (size_t) len
);
7703 pic
->pic_ChunksLen
-= chlen
;
7704 KPRINTF(10, ("Deleted %ld bytes to %ld chunk len\n", chlen
, pic
->pic_ChunksLen
));
7708 buf
= (ULONG
*) (((UBYTE
*) buf
) + chlen
);
7710 KPRINTF(10, ("Not found!\n"));
7715 /* /// "pAddCfgChunk()" */
7716 struct PsdIFFContext
* pAddCfgChunk(LIBBASETYPEPTR ps
, struct PsdIFFContext
*pic
, APTR chunk
)
7722 struct PsdIFFContext
*subpic
;
7723 KPRINTF(10, ("pAddCfgChunk(%p, %p)\n", pic
, chunk
));
7724 if(AROS_LONG2BE(*buf
) == ID_FORM
)
7727 len
= ((AROS_LONG2BE(*buf
)) - 3) & ~1UL;
7729 if((subpic
= pAllocForm(ps
, pic
, AROS_LONG2BE(*buf
))))
7734 if(!(pAddCfgChunk(ps
, subpic
, buf
)))
7738 chlen
= (AROS_LONG2BE(buf
[1]) + 9) & ~1UL;
7740 buf
= (ULONG
*) (((UBYTE
*) buf
) + chlen
);
7744 psdAddErrorMsg0(RETURN_FAIL
, (STRPTR
) GM_UNIQUENAME(libname
), "Tried to add a nasty corrupted FORM chunk! Configuration is probably b0rken!");
7752 pRemCfgChunk(ps
, pic
, AROS_LONG2BE(*buf
));
7753 len
= (AROS_LONG2BE(buf
[1]) + 9) & ~1UL;
7754 if(pic
->pic_ChunksLen
+len
> pic
->pic_BufferLen
)
7756 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
));
7759 if((newbuf
= psdAllocVec((pic
->pic_ChunksLen
+len
)<<1)))
7761 if(pic
->pic_ChunksLen
)
7763 memcpy(newbuf
, pic
->pic_Chunks
, (size_t) pic
->pic_ChunksLen
);
7764 psdFreeVec(pic
->pic_Chunks
);
7766 pic
->pic_Chunks
= newbuf
;
7767 pic
->pic_BufferLen
= (pic
->pic_ChunksLen
+len
)<<1;
7772 memcpy(&(((UBYTE
*) pic
->pic_Chunks
)[pic
->pic_ChunksLen
]), chunk
, (size_t) len
);
7773 pic
->pic_ChunksLen
+= len
;
7779 /* /// "pInternalWriteForm()" */
7780 ULONG
* pInternalWriteForm(struct PsdIFFContext
*pic
, ULONG
*buf
)
7782 struct PsdIFFContext
*subpic
= (struct PsdIFFContext
*) pic
->pic_SubForms
.lh_Head
;
7783 //KPRINTF(10, ("pInternalWriteForm(%p, %p)", pic, buf));
7784 *buf
++ = AROS_LONG2BE(ID_FORM
);
7785 *buf
++ = AROS_LONG2BE(pic
->pic_FormLength
);
7786 *buf
++ = AROS_LONG2BE(pic
->pic_FormID
);
7787 if(pic
->pic_ChunksLen
)
7789 memcpy(buf
, pic
->pic_Chunks
, (size_t) pic
->pic_ChunksLen
);
7790 buf
= (ULONG
*) (((UBYTE
*) buf
) + pic
->pic_ChunksLen
);
7792 while(subpic
->pic_Node
.ln_Succ
)
7794 buf
= pInternalWriteForm(subpic
, buf
);
7795 subpic
= (struct PsdIFFContext
*) subpic
->pic_Node
.ln_Succ
;
7801 /* /// "pCalcCfgCRC()" */
7802 ULONG
pCalcCfgCRC(struct PsdIFFContext
*pic
)
7804 struct PsdIFFContext
*subpic
= (struct PsdIFFContext
*) pic
->pic_SubForms
.lh_Head
;
7806 ULONG crc
= pic
->pic_FormID
;
7809 //KPRINTF(10, ("pInternalWriteForm(%p, %p)", pic, buf));
7810 if(pic
->pic_ChunksLen
)
7812 len
= pic
->pic_ChunksLen
>>1;
7815 ptr
= (UWORD
*) pic
->pic_Chunks
;
7818 crc
= ((crc
<<1)|(crc
>>31))^(*ptr
++);
7822 while(subpic
->pic_Node
.ln_Succ
)
7824 crc
^= pCalcCfgCRC(subpic
);
7825 subpic
= (struct PsdIFFContext
*) subpic
->pic_Node
.ln_Succ
;
7831 /* /// "pCheckCfgChanged()" */
7832 BOOL
pCheckCfgChanged(LIBBASETYPEPTR ps
)
7835 struct PsdIFFContext
*pic
;
7836 struct PsdIFFContext
*subpic
;
7839 pLockSemShared(ps
, &ps
->ps_ConfigLock
);
7840 ps
->ps_CheckConfigReq
= FALSE
;
7841 pic
= (struct PsdIFFContext
*) ps
->ps_ConfigRoot
.lh_Head
;
7842 if(!(pic
->pic_Node
.ln_Succ
))
7844 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
7847 crc
= pCalcCfgCRC(pic
);
7848 if(crc
!= ps
->ps_ConfigHash
)
7851 ps
->ps_ConfigHash
= crc
;
7852 /* Get Global config */
7853 if((subpic
= psdFindCfgForm(pic
, IFFFORM_STACKCFG
)))
7855 if((chnk
= pFindCfgChunk(ps
, subpic
, IFFCHNK_GLOBALCFG
)))
7857 CopyMem(&chnk
[2], ((UBYTE
*) ps
->ps_GlobalCfg
) + 8, min(AROS_LONG2BE(chnk
[1]), AROS_LONG2BE(ps
->ps_GlobalCfg
->pgc_Length
)));
7859 if(!pMatchStringChunk(ps
, subpic
, IFFCHNK_INSERTSND
, ps
->ps_PoPo
.po_InsertSndFile
))
7861 if((tmpstr
= pGetStringChunk(ps
, subpic
, IFFCHNK_INSERTSND
)))
7863 psdFreeVec(ps
->ps_PoPo
.po_InsertSndFile
);
7864 ps
->ps_PoPo
.po_InsertSndFile
= tmpstr
;
7867 if(!pMatchStringChunk(ps
, subpic
, IFFCHNK_REMOVESND
, ps
->ps_PoPo
.po_RemoveSndFile
))
7869 if((tmpstr
= pGetStringChunk(ps
, subpic
, IFFCHNK_REMOVESND
)))
7871 psdFreeVec(ps
->ps_PoPo
.po_RemoveSndFile
);
7872 ps
->ps_PoPo
.po_RemoveSndFile
= tmpstr
;
7876 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
7877 psdSendEvent(EHMB_CONFIGCHG
, NULL
, NULL
);
7880 pUnlockSem(ps
, &ps
->ps_ConfigLock
);
7885 /* /// "pAddStringChunk()" */
7886 BOOL
pAddStringChunk(LIBBASETYPEPTR ps
, struct PsdIFFContext
*pic
, ULONG chunkid
, CONST_STRPTR str
)
7889 ULONG len
= strlen(str
);
7890 ULONG
*chnk
= (ULONG
*) psdAllocVec((ULONG
) len
+8+2);
7893 chnk
[0] = AROS_LONG2BE(chunkid
);
7894 chnk
[1] = AROS_LONG2BE(len
+1);
7895 strcpy((STRPTR
) &chnk
[2], str
);
7896 if(pAddCfgChunk(ps
, pic
, chnk
))
7906 /* /// "pMatchStringChunk()" */
7907 BOOL
pMatchStringChunk(LIBBASETYPEPTR ps
, struct PsdIFFContext
*pic
, ULONG chunkid
, CONST_STRPTR str
)
7912 if((chunk
= pFindCfgChunk(ps
, pic
, chunkid
)))
7914 srcptr
= (STRPTR
) &chunk
[2];
7915 len
= AROS_LONG2BE(chunk
[1]);
7916 while(len
-- && *srcptr
)
7918 if(*str
++ != *srcptr
++)
7932 /* /// "pGetStringChunk()" */
7933 STRPTR
pGetStringChunk(LIBBASETYPEPTR ps
, struct PsdIFFContext
*pic
, ULONG chunkid
)
7937 if((chunk
= pFindCfgChunk(ps
, pic
, chunkid
)))
7939 if((str
= (STRPTR
) psdAllocVec(AROS_LONG2BE(chunk
[1]) + 1)))
7941 memcpy(str
, &chunk
[2], (size_t) AROS_LONG2BE(chunk
[1]));
7949 /* /// "pUpdateGlobalCfg()" */
7950 void pUpdateGlobalCfg(LIBBASETYPEPTR ps
, struct PsdIFFContext
*pic
)
7952 struct PsdIFFContext
*tmppic
;
7953 /* Set Global config */
7954 if(pic
== (struct PsdIFFContext
*) ps
->ps_ConfigRoot
.lh_Head
)
7956 if((tmppic
= psdFindCfgForm(NULL
, IFFFORM_STACKCFG
)))
7958 pAddCfgChunk(ps
, tmppic
, ps
->ps_GlobalCfg
);
7959 pAddStringChunk(ps
, tmppic
, IFFCHNK_INSERTSND
, ps
->ps_PoPo
.po_InsertSndFile
);
7960 pAddStringChunk(ps
, tmppic
, IFFCHNK_REMOVESND
, ps
->ps_PoPo
.po_RemoveSndFile
);
7966 /* *** Misc (non library functions) ***/
7968 /* /// "pGetDevConfig()" */
7969 BOOL
pGetDevConfig(struct PsdPipe
*pp
)
7971 struct PsdDevice
*pd
= pp
->pp_Device
;
7972 LIBBASETYPEPTR ps
= pd
->pd_Hardware
->phw_Base
;
7974 struct UsbStdCfgDesc uscd
;
7980 KPRINTF(1, ("Getting configuration descriptor...\n"));
7981 psdLockWriteDevice(pd
);
7982 while(curcfg
< pd
->pd_NumCfgs
)
7984 psdPipeSetup(pp
, URTF_IN
|URTF_STANDARD
|URTF_DEVICE
,
7985 USR_GET_DESCRIPTOR
, (UDT_CONFIGURATION
<<8)|curcfg
, 0);
7987 /*tempbuf = psdAllocVec(256);
7988 ioerr = psdDoPipe(pp, tempbuf, 34);
7989 if(ioerr == UHIOERR_RUNTPACKET)
7993 memcpy(&uscd, tempbuf, 9);*/
7994 ioerr
= psdDoPipe(pp
, &uscd
, 9);//sizeof(struct UsbStdCfgDesc));
7997 KPRINTF(1, ("Config type: %ld\n", (ULONG
) uscd
.bDescriptorType
));
7998 len
= (ULONG
) AROS_WORD2LE(uscd
.wTotalLength
);
7999 KPRINTF(1, ("Configsize %ld, total size %ld\n", (ULONG
) uscd
.bLength
, len
));
8000 if((tempbuf
= psdAllocVec(len
)))
8003 KPRINTF(1, ("Getting whole configuration descriptor...\n"));
8004 ioerr
= psdDoPipe(pp
, tempbuf
, len
);
8007 struct PsdConfig
*pc
= NULL
;
8008 struct PsdInterface
*pif
= NULL
;
8009 struct PsdInterface
*altif
= NULL
;
8010 struct PsdEndpoint
*pep
= NULL
;
8011 struct PsdDescriptor
*pdd
= NULL
;
8012 UBYTE
*dbuf
= tempbuf
;
8015 bufend
= &dbuf
[len
];
8016 while(dbuf
< bufend
)
8018 dlen
= dbuf
[0]; /* bLength */
8023 if(&dbuf
[dlen
] > bufend
)
8025 psdAddErrorMsg0(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
), "End of descriptor past buffer!");
8027 switch(dbuf
[1]) /* bDescriptorType */
8029 case UDT_CONFIGURATION
:
8031 struct UsbStdCfgDesc
*usc
= (struct UsbStdCfgDesc
*) dbuf
;
8035 if((pc
= pAllocConfig(pd
)))
8037 pd
->pd_Flags
|= PDFF_CONFIGURED
;
8038 pc
->pc_NumIfs
= usc
->bNumInterfaces
;
8039 pc
->pc_CfgNum
= usc
->bConfigurationValue
;
8040 pc
->pc_Attr
= usc
->bmAttributes
;
8041 pc
->pc_MaxPower
= usc
->bMaxPower
<<1;
8043 KPRINTF(1, (" Config %ld\n", pc
->pc_CfgNum
));
8044 if(usc
->iConfiguration
)
8046 pc
->pc_CfgStr
= psdGetStringDescriptor(pp
, usc
->iConfiguration
);
8050 pc
->pc_CfgStr
= psdCopyStrFmt("Configuration %ld", pc
->pc_CfgNum
);
8053 KPRINTF(20, (" Config allocation failed\n"));
8060 struct UsbStdIfDesc
*usif
= (struct UsbStdIfDesc
*) dbuf
;
8064 if((altif
= pAllocInterface(pc
)))
8066 altif
->pif_IfNum
= usif
->bInterfaceNumber
;
8067 altif
->pif_Alternate
= usif
->bAlternateSetting
;
8068 altif
->pif_NumEPs
= usif
->bNumEndpoints
;
8069 altif
->pif_IfClass
= usif
->bInterfaceClass
;
8070 altif
->pif_IfSubClass
= usif
->bInterfaceSubClass
;
8071 altif
->pif_IfProto
= usif
->bInterfaceProtocol
;
8072 KPRINTF(2, (" Interface %ld\n", altif
->pif_IfNum
));
8073 if(usif
->iInterface
)
8075 altif
->pif_IfStr
= psdGetStringDescriptor(pp
, usif
->iInterface
);
8077 if(!altif
->pif_IfStr
)
8079 classname
= psdNumToStr(NTS_CLASSCODE
, (LONG
) altif
->pif_IfClass
, NULL
);
8082 altif
->pif_IfStr
= psdCopyStrFmt("%s interface (%ld)", classname
, altif
->pif_IfNum
);
8084 altif
->pif_IfStr
= psdCopyStrFmt("Interface %ld", altif
->pif_IfNum
);
8087 KPRINTF(2, (" IfName : %s\n"
8088 " Alternate : %ld\n"
8091 " IfSubClass: %ld\n"
8093 altif
->pif_IfStr
, altif
->pif_Alternate
,
8096 altif
->pif_IfSubClass
, altif
->pif_IfProto
));
8097 if(pc
->pc_CfgNum
== 1)
8099 altif
->pif_IDString
= psdCopyStrFmt("%02lx-%02lx-%02lx-%02lx-%02lx",
8100 altif
->pif_IfNum
, altif
->pif_Alternate
,
8101 altif
->pif_IfClass
, altif
->pif_IfSubClass
,
8102 altif
->pif_IfProto
);
8104 // for more than one config, add config number (retain backwards compatibility with most devices)
8105 altif
->pif_IDString
= psdCopyStrFmt("%02lx-%02lx-%02lx-%02lx-%02lx-%02lx",
8107 altif
->pif_IfNum
, altif
->pif_Alternate
,
8108 altif
->pif_IfClass
, altif
->pif_IfSubClass
,
8109 altif
->pif_IfProto
);
8112 /* Move the interface to the alternatives if possible */
8113 if(altif
->pif_Alternate
)
8117 psdAddErrorMsg0(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
), "Alternate interface without prior main interface!");
8118 KPRINTF(20, (" Alternate interface without prior main interface\n"));
8121 Remove(&altif
->pif_Node
);
8122 AddTail(&pif
->pif_AlterIfs
, &altif
->pif_Node
);
8123 altif
->pif_ParentIf
= pif
;
8126 altif
->pif_ParentIf
= NULL
;
8130 KPRINTF(20, (" Interface allocation failed\n"));
8133 psdAddErrorMsg0(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
), "Interface without prior config descriptor!");
8134 KPRINTF(20, (" Interface descriptor without Config\n"));
8141 struct UsbStdEPDesc
*usep
= (struct UsbStdEPDesc
*) dbuf
;
8144 if((pep
= pAllocEndpoint(altif
)))
8147 pep
->pep_EPNum
= usep
->bEndpointAddress
& 0x0f;
8148 pep
->pep_Direction
= usep
->bEndpointAddress
>>7;
8149 pep
->pep_TransType
= usep
->bmAttributes
& 0x03;
8150 pep
->pep_SyncType
= (usep
->bmAttributes
>>2) & 0x03;
8151 pep
->pep_UsageType
= (usep
->bmAttributes
>>4) & 0x03;
8152 eptype
= (pep
->pep_TransType
== USEAF_INTERRUPT
) ? "int" : "iso";
8154 pep
->pep_MaxPktSize
= AROS_WORD2LE(usep
->wMaxPacketSize
) & 0x07ff;
8155 pep
->pep_NumTransMuFr
= ((AROS_WORD2LE(usep
->wMaxPacketSize
)>>11) & 3) + 1;
8156 if(pep
->pep_NumTransMuFr
== 4)
8158 psdAddErrorMsg0(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Endpoint contains illegal Num Trans µFrame value!");
8159 pep
->pep_NumTransMuFr
= 1;
8162 pep
->pep_Interval
= usep
->bInterval
;
8163 if(pd
->pd_Flags
& PDFF_HIGHSPEED
)
8165 switch(pep
->pep_TransType
)
8169 //pep->pep_Interval = 0; // no use here, NAK rate not of interest
8172 case USEAF_ISOCHRONOUS
:
8173 if(pep
->pep_MaxPktSize
> 1024)
8175 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
8176 "Endpoint contains %s (%ld) MaxPktSize value!",
8177 (STRPTR
) "too high", pep
->pep_MaxPktSize
);
8178 pep
->pep_MaxPktSize
= 1024;
8181 case USEAF_INTERRUPT
:
8182 if(!pep
->pep_Interval
)
8184 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
8185 "%sspeed %s endpoint contains %s interval value! Fixing.",
8186 (STRPTR
) "High", eptype
, (STRPTR
) "zero");
8187 pep
->pep_Interval
= 1;
8189 else if(pep
->pep_Interval
> 16)
8191 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
8192 "%sspeed %s endpoint contains %s interval value! Fixing.",
8193 (STRPTR
) "High", eptype
, (STRPTR
) "too high");
8194 pep
->pep_Interval
= 16;
8196 pep
->pep_Interval
= 1<<(pep
->pep_Interval
-1);
8200 else if(pd
->pd_Flags
& PDFF_LOWSPEED
)
8202 switch(pep
->pep_TransType
)
8204 case USEAF_INTERRUPT
:
8205 if(pep
->pep_Interval
< 8)
8207 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "%sspeed %s endpoint contains %s interval value! Fixing.",
8208 (STRPTR
) "Low", eptype
, (STRPTR
) "too low");
8209 pep
->pep_Interval
= 8;
8215 pep
->pep_Interval
= 0; // no use here
8218 case USEAF_ISOCHRONOUS
:
8219 psdAddErrorMsg0(RETURN_ERROR
, (STRPTR
) GM_UNIQUENAME(libname
), "Lowspeed devices cannot have isochronous endpoints!");
8223 switch(pep
->pep_TransType
)
8225 case USEAF_INTERRUPT
:
8226 if(!pep
->pep_Interval
)
8228 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "%sspeed %s endpoint contains %s interval value! Fixing.",
8229 (STRPTR
) "Full", eptype
, (STRPTR
) "zero");
8230 pep
->pep_Interval
= 1;
8236 pep
->pep_Interval
= 0; // no use here
8239 case USEAF_ISOCHRONOUS
:
8240 if(pep
->pep_MaxPktSize
> 1023)
8242 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Endpoint contains too high (%ld) MaxPktSize value! Fixing.", pep
->pep_MaxPktSize
);
8243 pep
->pep_MaxPktSize
= 1023;
8245 if(!pep
->pep_Interval
)
8247 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "%sspeed %s endpoint contains %s interval value! Fixing.",
8248 (STRPTR
) "Full", eptype
, (STRPTR
) "zero");
8249 pep
->pep_Interval
= 1;
8251 else if(pep
->pep_Interval
> 16)
8253 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "%sspeed %s endpoint contains %s interval value! Fixing.",
8254 (STRPTR
) "Full", eptype
, (STRPTR
) "too high");
8255 pep
->pep_Interval
= 16;
8257 pep
->pep_Interval
= 1<<(pep
->pep_Interval
-1);
8262 KPRINTF(2, (" Endpoint %ld\n", pep
->pep_EPNum
));
8263 KPRINTF(2, (" Direction : %s\n"
8264 " TransType : %ld\n"
8265 " MaxPktSize: %ld\n"
8266 " Interval : %ld\n",
8267 (pep
->pep_Direction
? "IN" : "OUT"),
8268 pep
->pep_TransType
, pep
->pep_MaxPktSize
,
8269 pep
->pep_Interval
));
8272 KPRINTF(20, (" Endpoint allocation failed\n"));
8275 psdAddErrorMsg0(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Endpoint without prior interface descriptor!");
8276 KPRINTF(20, (" Endpoint descriptor without Interface\n"));
8286 case UDT_CS_INTERFACE
:
8287 case UDT_CS_ENDPOINT
:
8288 case UDT_DEVICE_QUALIFIER
:
8289 case UDT_OTHERSPEED_QUALIFIER
:
8290 case UDT_INTERFACE_POWER
:
8292 //psdAddErrorMsg(RETURN_WARN, (STRPTR) GM_UNIQUENAME(libname), "Skipping descriptor %02lx (pc=%p, pif=%p altpif=%p).", dbuf[1], pc, pif, altif);
8293 KPRINTF(1, ("Skipping unknown descriptor %ld.\n", dbuf
[1]));
8297 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Skipping unknown descriptor %02lx.", dbuf
[1]);
8298 KPRINTF(1, ("Skipping unknown descriptor %ld.\n", dbuf
[1]));
8301 // add descriptor to device
8302 pdd
= pAllocDescriptor(pd
, dbuf
);
8305 STRPTR descname
= NULL
;
8307 pdd
->pdd_Config
= pc
;
8308 pdd
->pdd_Interface
= altif
;
8309 pdd
->pdd_Endpoint
= pep
;
8310 if(pdd
->pdd_Interface
)
8312 if((pdd
->pdd_Type
>= UDT_CS_UNDEFINED
) && (pdd
->pdd_Type
<= UDT_CS_ENDPOINT
))
8314 descname
= psdNumToStr(NTS_DESCRIPTOR
, (LONG
) (pdd
->pdd_CSSubType
<<24)|(pif
->pif_IfSubClass
<<16)|(pif
->pif_IfClass
<<8)|pdd
->pdd_Type
, NULL
);
8317 descname
= psdNumToStr(NTS_DESCRIPTOR
, (LONG
) (pdd
->pdd_CSSubType
<<24)|(pif
->pif_IfClass
<<8)|pdd
->pdd_Type
, NULL
);
8322 descname
= psdNumToStr(NTS_DESCRIPTOR
, (LONG
) (pif
->pif_IfSubClass
<<16)|(pif
->pif_IfClass
<<8)|pdd
->pdd_Type
, NULL
);
8326 descname
= psdNumToStr(NTS_DESCRIPTOR
, (LONG
) (pif
->pif_IfClass
<<8)|pdd
->pdd_Type
, NULL
);
8331 pdd
->pdd_Name
= descname
;
8336 KPRINTF(1, ("Configuration acquired!\n"));
8337 psdFreeVec(tempbuf
);
8340 //psdUnlockDevice(pd);
8343 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
8344 "GET_DESCRIPTOR (len %ld) failed: %s (%ld)",
8345 len
, psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
8346 KPRINTF(15, ("GET_DESCRIPTOR failed %ld!\n", ioerr
));
8348 psdFreeVec(tempbuf
);
8350 KPRINTF(20, ("No memory for %ld bytes config temp buffer!\n", len
));
8353 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
8354 "GET_DESCRIPTOR (len %ld) failed: %s (%ld)",
8355 9, psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
8356 KPRINTF(15, ("GET_DESCRIPTOR (9) failed %ld!\n", ioerr
));
8358 psdUnlockDevice(pd
);
8361 psdUnlockDevice(pd
);
8366 /* /// "pPowerRecurseDrain()" */
8367 ULONG
pPowerRecurseDrain(LIBBASETYPEPTR ps
, struct PsdDevice
*pd
)
8369 struct PsdDevice
*nextpd
;
8370 struct PsdConfig
*pc
;
8371 UWORD maxdrain
= 666;
8373 BOOL selfpwd
= TRUE
;
8374 pd
->pd_PowerDrain
= 0;
8376 /* look at config */
8377 if((pc
= pd
->pd_CurrentConfig
))
8380 /* if suspended, no more than 500µA are drained */
8381 if(pd
->pd_Flags
& PDFF_SUSPENDED
)
8383 pd
->pd_PowerDrain
= (pc
->pc_MaxPower
>= 100) ? 3 : 1;
8384 return(pd
->pd_PowerDrain
);
8386 selfpwd
= ((pc
->pc_Attr
& USCAF_SELF_POWERED
) && (pd
->pd_PoPoCfg
.poc_OverridePowerInfo
!= POCP_BUS_POWERED
)) ||
8387 (pd
->pd_PoPoCfg
.poc_OverridePowerInfo
== POCP_SELF_POWERED
);
8388 maxdrain
= selfpwd
? 500 : 100;
8391 /* examine children */
8392 nextpd
= (struct PsdDevice
*) pd
->pd_Hardware
->phw_Devices
.lh_Head
;
8393 while(nextpd
->pd_Node
.ln_Succ
)
8395 if(nextpd
->pd_Hub
== pd
)
8397 childdrain
= pPowerRecurseDrain(ps
, nextpd
);
8398 // limit the drain to the maximum power suckage
8399 pd
->pd_PowerDrain
+= (childdrain
> maxdrain
) ? maxdrain
: childdrain
;
8401 nextpd
= (struct PsdDevice
*) nextpd
->pd_Node
.ln_Succ
;
8404 /* look at config */
8407 pd
->pd_PowerDrain
= 0;
8409 pd
->pd_PowerDrain
+= pc
->pc_MaxPower
;
8411 return(pd
->pd_PowerDrain
);
8415 /* /// "pPowerRecurseSupply()" */
8416 void pPowerRecurseSupply(LIBBASETYPEPTR ps
, struct PsdDevice
*pd
)
8418 struct PsdDevice
*nextpd
;
8419 struct PsdConfig
*pc
;
8422 BOOL selfpwd
= TRUE
;
8424 /* look at config */
8425 if((pc
= pd
->pd_CurrentConfig
))
8427 selfpwd
= ((pc
->pc_Attr
& USCAF_SELF_POWERED
) && (pd
->pd_PoPoCfg
.poc_OverridePowerInfo
!= POCP_BUS_POWERED
)) ||
8428 (pd
->pd_PoPoCfg
.poc_OverridePowerInfo
== POCP_SELF_POWERED
);
8431 /* count children */
8432 nextpd
= (struct PsdDevice
*) pd
->pd_Hardware
->phw_Devices
.lh_Head
;
8433 while(nextpd
->pd_Node
.ln_Succ
)
8435 if(nextpd
->pd_Hub
== pd
) // this device is a child of us (we're a hub!)
8439 nextpd
= (struct PsdDevice
*) nextpd
->pd_Node
.ln_Succ
;
8442 /* look at config */
8447 pd
->pd_PowerSupply
= ports
? 500*ports
+ pc
->pc_MaxPower
: pc
->pc_MaxPower
;
8449 supply
= 500; // each downstream port gets the full monty
8451 // the parent hub has already set the amount of supply for this port
8452 if(pd
->pd_PowerSupply
>= pc
->pc_MaxPower
)
8454 // the downstream ports get the remaining divided attention
8457 // avoid division by zero
8458 supply
= (pd
->pd_PowerSupply
- pc
->pc_MaxPower
) / ports
;
8461 // limit to 100 mA per port
8466 supply
= 1; // bad luck, out of power
8471 if(ports
) /* needs to be a hub */
8473 // propagate supply down to the children
8474 nextpd
= (struct PsdDevice
*) pd
->pd_Hardware
->phw_Devices
.lh_Head
;
8475 while(nextpd
->pd_Node
.ln_Succ
)
8477 if(nextpd
->pd_Hub
== pd
)
8479 nextpd
->pd_PowerSupply
= supply
;
8480 pPowerRecurseSupply(ps
, nextpd
);
8482 nextpd
= (struct PsdDevice
*) nextpd
->pd_Node
.ln_Succ
;
8485 if(pd
->pd_PowerDrain
> pd
->pd_PowerSupply
)
8487 if(!(pd
->pd_Flags
& PDFF_LOWPOWER
))
8489 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
8490 "Detected low power condition for '%s'.", pd
->pd_ProductStr
);
8491 pd
->pd_Flags
|= PDFF_LOWPOWER
;
8492 psdSendEvent(EHMB_DEVICELOWPW
, pd
, NULL
);
8495 if(pd
->pd_Flags
& PDFF_LOWPOWER
)
8497 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
),
8498 "Low power condition resolved for '%s'.", pd
->pd_ProductStr
);
8499 pd
->pd_Flags
&= ~PDFF_LOWPOWER
;
8505 /* /// "pGarbageCollectEvents()" */
8506 void pGarbageCollectEvents(LIBBASETYPEPTR ps
)
8508 struct PsdEventNote
*pen
;
8509 while((pen
= (struct PsdEventNote
*) GetMsg(&ps
->ps_EventReplyPort
)))
8516 /* /// "pFindName()" */
8517 struct Node
* pFindName(LIBBASETYPEPTR ps
, struct List
*list
, STRPTR name
)
8519 struct Node
*res
= NULL
;
8524 res
= FindName(list
, name
);
8531 if((*name
== '/') || (*name
== ':'))
8543 /* /// "pStripString()" */
8544 void pStripString(LIBBASETYPEPTR ps
, STRPTR str
)
8546 STRPTR srcptr
= str
;
8547 STRPTR tarptr
= str
;
8548 STRPTR lastgoodchar
= str
;
8549 BOOL leadingspaces
= TRUE
;
8553 while((ch
= *srcptr
++))
8564 lastgoodchar
= tarptr
;
8565 leadingspaces
= FALSE
;
8570 if((str
== lastgoodchar
) && (len
> 6))
8572 strcpy(str
, "<empty>");
8577 /* /// "pFixBrokenConfig()" */
8578 BOOL
pFixBrokenConfig(struct PsdPipe
*pp
)
8580 struct PsdDevice
*pd
= pp
->pp_Device
;
8581 LIBBASETYPEPTR ps
= pd
->pd_Hardware
->phw_Base
;
8582 struct PsdConfig
*pc
;
8583 struct PsdInterface
*pif
;
8586 switch(pd
->pd_VendorID
)
8588 case 0x03eb: /* Atmel */
8589 if(pd
->pd_ProductID
== 0x3312)
8591 psdFreeVec(pd
->pd_ProductStr
);
8592 pd
->pd_ProductStr
= psdCopyStr("Highway/Subway Root Hub");
8596 case 0x04e6: /* E-Shuttle */
8597 if(pd
->pd_ProductID
== 0x0001) /* LS120 */
8599 pc
= (struct PsdConfig
*) pd
->pd_Configs
.lh_Head
;
8600 /* Get msd interface and fix it */
8601 pif
= (struct PsdInterface
*) pc
->pc_Interfaces
.lh_Head
;
8602 if(pif
->pif_IfClass
!= MASSSTORE_CLASSCODE
)
8605 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Fixing broken %s interface descriptor!", (STRPTR
) "E-Shuttle LS120");
8606 pif
->pif_IfClass
= MASSSTORE_CLASSCODE
;
8607 pif
->pif_IfSubClass
= MS_ATAPI_SUBCLASS
;
8608 pif
->pif_IfProto
= MS_PROTO_CB
;
8613 case 0x054C: /* Sony */
8614 if((pd
->pd_ProductID
== 0x002E) || (pd
->pd_ProductID
== 0x0010)) /* Handycam */
8617 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Fixing broken %s interface descriptor!", (STRPTR
) "Sony MSD");
8618 pc
= (struct PsdConfig
*) pd
->pd_Configs
.lh_Head
;
8619 /* Get msd interface and fix it */
8620 pif
= (struct PsdInterface
*) pc
->pc_Interfaces
.lh_Head
;
8621 pif
->pif_IfSubClass
= MS_RBC_SUBCLASS
;
8625 case 0x057b: /* Y-E Data */
8626 if(pd
->pd_ProductID
== 0x0000) /* Flashbuster U */
8628 pc
= (struct PsdConfig
*) pd
->pd_Configs
.lh_Head
;
8629 /* Get msd interface and fix it */
8630 pif
= (struct PsdInterface
*) pc
->pc_Interfaces
.lh_Head
;
8631 if(pif
->pif_IfClass
!= MASSSTORE_CLASSCODE
)
8634 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Fixing broken %s interface descriptor!", (STRPTR
) "Y-E Data USB Floppy");
8635 pif
->pif_IfClass
= MASSSTORE_CLASSCODE
;
8636 pif
->pif_IfSubClass
= MS_UFI_SUBCLASS
;
8637 pif
->pif_IfProto
= (pd
->pd_DevVers
< 0x0300) ? MS_PROTO_CB
: MS_PROTO_CBI
;
8642 case 0x04ce: /* ScanLogic */
8643 if(pd
->pd_ProductID
== 0x0002)
8645 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Fixing broken %s interface descriptor!", (STRPTR
) "ScanLogic");
8646 pc
= (struct PsdConfig
*) pd
->pd_Configs
.lh_Head
;
8647 /* Get msd interface and fix it */
8648 pif
= (struct PsdInterface
*) pc
->pc_Interfaces
.lh_Head
;
8650 pif
->pif_IfSubClass
= MS_SCSI_SUBCLASS
;
8654 case 0x0584: /* Ratoc cardreader */
8655 if(pd
->pd_ProductID
== 0x0008)
8657 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Fixing broken %s interface descriptor!", (STRPTR
) "RATOC");
8658 pc
= (struct PsdConfig
*) pd
->pd_Configs
.lh_Head
;
8659 /* Get msd interface and fix it */
8660 pif
= (struct PsdInterface
*) pc
->pc_Interfaces
.lh_Head
;
8662 pif
->pif_IfClass
= MASSSTORE_CLASSCODE
;
8663 pif
->pif_IfSubClass
= MS_SCSI_SUBCLASS
;
8664 pif
->pif_IfProto
= MS_PROTO_BULK
;
8668 case 0x04b8: /* Epson */
8669 if(pd
->pd_ProductID
== 0x0602) /* EPX Storage device (Card slot in Printer) */
8671 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
), "Fixing broken %s interface descriptor!", (STRPTR
) "Epson storage");
8672 pc
= (struct PsdConfig
*) pd
->pd_Configs
.lh_Head
;
8673 /* Get msd interface and fix it */
8674 pif
= (struct PsdInterface
*) pc
->pc_Interfaces
.lh_Head
;
8676 pif
->pif_IfClass
= MASSSTORE_CLASSCODE
;
8677 pif
->pif_IfSubClass
= MS_SCSI_SUBCLASS
;
8678 pif
->pif_IfProto
= MS_PROTO_BULK
;
8689 /* /// "pOpenDOS()" */
8690 BOOL
pOpenDOS(LIBBASETYPEPTR ps
)
8696 if((DOSBase
= OpenLibrary("dos.library", 39)))
8704 /* *** Class Scan Task *** */
8706 /* /// "pStartEventHandler()" */
8707 BOOL
pStartEventHandler(LIBBASETYPEPTR ps
)
8709 struct PsdHandlerTask
*ph
= &ps
->ps_EventHandler
;
8711 ObtainSemaphore(&ps
->ps_PoPoLock
);
8714 ReleaseSemaphore(&ps
->ps_PoPoLock
);
8717 ph
->ph_ReadySignal
= SIGB_SINGLE
;
8718 ph
->ph_ReadySigTask
= FindTask(NULL
);
8719 SetSignal(0, SIGF_SINGLE
); // clear single bit
8720 if(psdSpawnSubTask("Poseidon Event Broadcast", pEventHandlerTask
, ps
))
8722 Wait(1UL<<ph
->ph_ReadySignal
);
8724 ph
->ph_ReadySigTask
= NULL
;
8725 //FreeSignal(ph->ph_ReadySignal);
8728 ReleaseSemaphore(&ps
->ps_PoPoLock
);
8729 psdAddErrorMsg0(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
), "Event broadcaster started.");
8732 ReleaseSemaphore(&ps
->ps_PoPoLock
);
8737 /* *** Hardware Driver Task *** */
8739 /* /// "pQuickForwardRequest()" */
8740 AROS_UFH1(void, pQuickForwardRequest
,
8741 AROS_UFHA(struct MsgPort
*, msgport
, A1
))
8744 struct PsdHardware
*phw
= (struct PsdHardware
*) msgport
->mp_Node
.ln_Name
;
8747 while((pp
= (struct PsdPipe
*) RemHead(&msgport
->mp_MsgList
)))
8749 if(pp
->pp_AbortPipe
)
8751 KPRINTF(2, ("Abort pipe %p\n", pp
->pp_AbortPipe
));
8752 AbortIO((struct IORequest
*) &pp
->pp_AbortPipe
->pp_IOReq
);
8753 ReplyMsg(&pp
->pp_Msg
);
8754 KPRINTF(2, ("Replying evil pipe %p\n", pp
));
8756 KPRINTF(1, ("Forwarding pipe %p\n", pp
));
8757 pp
->pp_IOReq
.iouh_UserData
= pp
;
8758 SendIO((struct IORequest
*) &pp
->pp_IOReq
);
8759 ++phw
->phw_MsgCount
;
8766 /* /// "pQuickReplyRequest()" */
8767 AROS_UFH1(void, pQuickReplyRequest
,
8768 AROS_UFHA(struct MsgPort
*, msgport
, A1
))
8771 struct PsdHardware
*phw
= (struct PsdHardware
*) msgport
->mp_Node
.ln_Name
;
8772 struct IOUsbHWReq
*ioreq
;
8774 while((ioreq
= (struct IOUsbHWReq
*) RemHead(&msgport
->mp_MsgList
)))
8776 KPRINTF(1, ("Replying pipe %p\n", ioreq
->iouh_UserData
));
8777 ReplyMsg(&((struct PsdPipe
*) ioreq
->iouh_UserData
)->pp_Msg
);
8778 --phw
->phw_MsgCount
;
8784 /* /// "pDeviceTask()" */
8785 AROS_UFH0(void, pDeviceTask
)
8789 struct PsdHardware
*phw
;
8790 struct Task
*thistask
;
8794 struct TagItem taglist
[11];
8795 struct TagItem
*tag
;
8797 struct IOUsbHWReq
*ioreq
;
8799 STRPTR prodname
= NULL
;
8800 STRPTR manufacturer
= NULL
;
8801 STRPTR description
= NULL
;
8802 STRPTR copyright
= NULL
;
8805 ULONG driververs
= 0x0100;
8806 ULONG caps
= UHCF_ISO
;
8810 if(!(ps
= (LIBBASETYPEPTR
) OpenLibrary("poseidon.library", 4)))
8815 thistask
= FindTask(NULL
);
8816 SetTaskPri(thistask
, 21);
8817 phw
= thistask
->tc_UserData
;
8819 #ifndef PA_CALLBACK // undocumented exec feature
8820 #define PA_CALLBACK 3
8823 phw
->phw_TaskMsgPort
.mp_Node
.ln_Type
= NT_MSGPORT
;
8824 phw
->phw_TaskMsgPort
.mp_Node
.ln_Name
= (APTR
) phw
;
8825 phw
->phw_TaskMsgPort
.mp_Flags
= PA_SIGNAL
;
8826 phw
->phw_TaskMsgPort
.mp_SigTask
= thistask
;
8827 phw
->phw_TaskMsgPort
.mp_SigBit
= AllocSignal(-1L);
8828 NewList(&phw
->phw_TaskMsgPort
.mp_MsgList
);
8830 phw
->phw_DevMsgPort
.mp_Node
.ln_Type
= NT_MSGPORT
;
8831 phw
->phw_DevMsgPort
.mp_Node
.ln_Name
= (APTR
) phw
;
8832 phw
->phw_DevMsgPort
.mp_Flags
= PA_SIGNAL
;
8833 phw
->phw_DevMsgPort
.mp_SigTask
= thistask
;
8834 phw
->phw_DevMsgPort
.mp_SigBit
= AllocSignal(-1L);
8835 NewList(&phw
->phw_DevMsgPort
.mp_MsgList
);
8837 if((phw
->phw_RootIOReq
= (struct IOUsbHWReq
*) CreateIORequest(&phw
->phw_DevMsgPort
, sizeof(struct IOUsbHWReq
))))
8839 devname
= phw
->phw_DevName
;
8843 if(!(ioerr
= OpenDevice(devname
, phw
->phw_Unit
, (struct IORequest
*) phw
->phw_RootIOReq
, 0)))
8849 if((*devname
== '/') || (*devname
== ':'))
8854 } while(*(++devname
));
8859 phw
->phw_Node
.ln_Name
= phw
->phw_RootIOReq
->iouh_Req
.io_Device
->dd_Library
.lib_Node
.ln_Name
;
8861 tag
->ti_Tag
= UHA_ProductName
;
8862 tag
->ti_Data
= (IPTR
) &prodname
;
8864 tag
->ti_Tag
= UHA_Manufacturer
;
8865 tag
->ti_Data
= (IPTR
) &manufacturer
;
8867 tag
->ti_Tag
= UHA_Description
;
8868 tag
->ti_Data
= (IPTR
) &description
;
8870 tag
->ti_Tag
= UHA_Version
;
8871 tag
->ti_Data
= (IPTR
) &version
;
8873 tag
->ti_Tag
= UHA_Revision
;
8874 tag
->ti_Data
= (IPTR
) &revision
;
8876 tag
->ti_Tag
= UHA_Copyright
;
8877 tag
->ti_Data
= (IPTR
) ©right
;
8879 tag
->ti_Tag
= UHA_DriverVersion
;
8880 tag
->ti_Data
= (IPTR
) &driververs
;
8882 tag
->ti_Tag
= UHA_Capabilities
;
8883 tag
->ti_Data
= (IPTR
) &caps
;
8885 tag
->ti_Tag
= TAG_END
;
8886 phw
->phw_RootIOReq
->iouh_Data
= taglist
;
8887 phw
->phw_RootIOReq
->iouh_Req
.io_Command
= UHCMD_QUERYDEVICE
;
8888 DoIO((struct IORequest
*) phw
->phw_RootIOReq
);
8890 phw
->phw_ProductName
= psdCopyStr(prodname
? prodname
: (STRPTR
) "n/a");
8891 phw
->phw_Manufacturer
= psdCopyStr(manufacturer
? manufacturer
: (STRPTR
) "n/a");
8892 phw
->phw_Description
= psdCopyStr(description
? description
: (STRPTR
) "n/a");
8893 phw
->phw_Copyright
= psdCopyStr(copyright
? copyright
: (STRPTR
) "n/a");
8894 phw
->phw_Version
= version
;
8895 phw
->phw_Revision
= revision
;
8896 phw
->phw_DriverVers
= driververs
;
8897 phw
->phw_Capabilities
= caps
;
8899 sigmask
= SIGBREAKF_CTRL_C
;
8900 if(caps
& UHCF_QUICKIO
)
8902 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
), "Enabling QuickIO for %s.", prodname
);
8903 phw
->phw_TaskMsgPort
.mp_Flags
= PA_CALLBACK
;
8904 phw
->phw_TaskMsgPort
.mp_SigTask
= (APTR
) pQuickForwardRequest
;
8906 phw
->phw_DevMsgPort
.mp_Flags
= PA_CALLBACK
;
8907 phw
->phw_DevMsgPort
.mp_SigTask
= (APTR
) pQuickReplyRequest
;
8909 sigmask
|= (1UL<<phw
->phw_DevMsgPort
.mp_SigBit
)|(1UL<<phw
->phw_TaskMsgPort
.mp_SigBit
);
8912 KPRINTF(10, ("%s ready!\n", thistask
->tc_Node
.ln_Name
));
8913 phw
->phw_Task
= thistask
;
8915 psdLockWritePBase();
8916 AddTail(&ps
->ps_Hardware
, &phw
->phw_Node
);
8920 if(phw
->phw_ReadySigTask
)
8922 Signal(phw
->phw_ReadySigTask
, 1L<<phw
->phw_ReadySignal
);
8927 KPRINTF(1, ("Main loop wait.\n"));
8928 while((pp
= (struct PsdPipe
*) GetMsg(&phw
->phw_TaskMsgPort
)))
8930 if(pp
->pp_AbortPipe
)
8932 KPRINTF(2, ("Abort pipe %p\n", pp
->pp_AbortPipe
));
8933 AbortIO((struct IORequest
*) &pp
->pp_AbortPipe
->pp_IOReq
);
8934 ReplyMsg(&pp
->pp_Msg
);
8935 KPRINTF(2, ("Replying evil pipe %p\n", pp
));
8937 KPRINTF(1, ("Forwarding pipe %p\n", pp
));
8938 pp
->pp_IOReq
.iouh_UserData
= pp
;
8939 SendIO((struct IORequest
*) &pp
->pp_IOReq
);
8940 ++phw
->phw_MsgCount
;
8943 while((ioreq
= (struct IOUsbHWReq
*) GetMsg(&phw
->phw_DevMsgPort
)))
8945 KPRINTF(1, ("Replying pipe %p\n", ioreq
->iouh_UserData
));
8946 ReplyMsg(&((struct PsdPipe
*) ioreq
->iouh_UserData
)->pp_Msg
);
8947 --phw
->phw_MsgCount
;
8949 sigs
= Wait(sigmask
);
8950 } while(!(sigs
& SIGBREAKF_CTRL_C
));
8951 /* Flush all pending IO Requests */
8952 phw
->phw_RootIOReq
->iouh_Req
.io_Command
= CMD_FLUSH
;
8953 DoIO((struct IORequest
*) phw
->phw_RootIOReq
);
8955 while(phw
->phw_MsgCount
)
8957 KPRINTF(20, ("Still %ld iorequests pending!\n", phw
->phw_MsgCount
));
8961 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
8962 "There are still %ld IORequests pending, before unit can go down. Driver buggy?",
8967 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) GM_UNIQUENAME(libname
),
8968 "Okay, I've waited long enough, sod these %ld IORequests.",
8970 phw
->phw_MsgCount
= 0;
8973 while((ioreq
= (struct IOUsbHWReq
*) GetMsg(&phw
->phw_DevMsgPort
)))
8975 KPRINTF(1, ("Replying pipe %p\n", ioreq
->iouh_UserData
));
8976 ReplyMsg(&((struct PsdPipe
*) ioreq
->iouh_UserData
)->pp_Msg
);
8977 --phw
->phw_MsgCount
;
8980 psdLockWritePBase();
8981 Remove(&phw
->phw_Node
);
8983 CloseDevice((struct IORequest
*) phw
->phw_RootIOReq
);
8985 psdAddErrorMsg(RETURN_FAIL
, (STRPTR
) GM_UNIQUENAME(libname
),
8986 "Opening %s unit %ld failed %s (%ld).",
8987 phw
->phw_DevName
, phw
->phw_Unit
, psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
8989 DeleteIORequest((struct IORequest
*) phw
->phw_RootIOReq
);
8990 phw
->phw_RootIOReq
= NULL
;
8992 FreeSignal((LONG
) phw
->phw_TaskMsgPort
.mp_SigBit
);
8993 FreeSignal((LONG
) phw
->phw_DevMsgPort
.mp_SigBit
);
8995 CloseLibrary((struct Library
*) ps
);
8996 phw
->phw_Task
= NULL
;
8999 if(phw
->phw_ReadySigTask
)
9001 Signal(phw
->phw_ReadySigTask
, 1L<<phw
->phw_ReadySignal
);
9007 /* /// "pEventHandlerTask()" */
9008 AROS_UFH0(void, pEventHandlerTask
)
9012 struct Task
*thistask
;
9013 struct timeval currtime
;
9016 struct PsdUsbClass
*puc
;
9017 struct PsdHandlerTask
*ph
;
9018 struct PsdEventNote
*pen
;
9022 thistask
= FindTask(NULL
);
9023 ps
= thistask
->tc_UserData
;
9024 ph
= &ps
->ps_EventHandler
;
9025 SetTaskPri(thistask
, 0);
9027 if((ph
->ph_MsgPort
= CreateMsgPort()))
9029 if((ph
->ph_TimerMsgPort
= CreateMsgPort()))
9031 if((ph
->ph_TimerIOReq
= (struct timerequest
*) CreateIORequest(ph
->ph_TimerMsgPort
, sizeof(struct timerequest
))))
9033 if(!(OpenDevice("timer.device", UNIT_VBLANK
, (struct IORequest
*) ph
->ph_TimerIOReq
, 0)))
9035 ph
->ph_TimerIOReq
->tr_node
.io_Message
.mn_Node
.ln_Type
= NT_REPLYMSG
;
9036 ph
->ph_TimerIOReq
->tr_node
.io_Message
.mn_Node
.ln_Name
= "EventHandler";
9037 ph
->ph_TimerIOReq
->tr_node
.io_Command
= TR_ADDREQUEST
;
9039 ph
->ph_EventHandler
= psdAddEventHandler(ph
->ph_MsgPort
, EHMF_CONFIGCHG
);
9040 if(ph
->ph_EventHandler
)
9042 ph
->ph_Task
= thistask
;
9044 if(ph
->ph_ReadySigTask
)
9046 Signal(ph
->ph_ReadySigTask
, 1L<<ph
->ph_ReadySignal
);
9050 ph
->ph_TimerIOReq
->tr_time
.tv_micro
= 500*1000;
9051 SendIO(&ph
->ph_TimerIOReq
->tr_node
);
9052 sigmask
= (1UL<<ph
->ph_MsgPort
->mp_SigBit
)|(1UL<<ph
->ph_TimerMsgPort
->mp_SigBit
)|SIGBREAKF_CTRL_C
;
9057 if(ps
->ps_CheckConfigReq
)
9059 pCheckCfgChanged(ps
);
9061 while((pen
= (struct PsdEventNote
*) GetMsg(ph
->ph_MsgPort
)))
9063 switch(pen
->pen_Event
)
9065 case EHMB_CONFIGCHG
:
9068 cfgchanged
= counter
;
9073 ReplyMsg(&pen
->pen_Msg
);
9075 if(CheckIO(&ph
->ph_TimerIOReq
->tr_node
))
9078 WaitIO(&ph
->ph_TimerIOReq
->tr_node
);
9079 ph
->ph_TimerIOReq
->tr_time
.tv_micro
= 500*1000;
9080 SendIO(&ph
->ph_TimerIOReq
->tr_node
);
9082 startpopo
= !((counter
& 3) || ps
->ps_PoPo
.po_Task
);
9083 if((ps
->ps_GlobalCfg
->pgc_PopupDeviceNew
== PGCP_NEVER
) &&
9084 (!ps
->ps_GlobalCfg
->pgc_PopupDeviceDeath
) &&
9085 (!ps
->ps_GlobalCfg
->pgc_PopupDeviceGone
))
9087 startpopo
= FALSE
; // no need to start popo, no windows wanted
9091 struct PsdPoPo
*po
= &ps
->ps_PoPo
;
9093 po
->po_ReadySignal
= SIGB_SINGLE
;
9094 po
->po_ReadySigTask
= FindTask(NULL
);
9095 SetSignal(0, SIGF_SINGLE
); // clear single bit
9096 if(psdSpawnSubTask("PoPo (Poseidon Popups)", pPoPoGUITask
, ps
))
9098 Wait(1UL<<po
->po_ReadySignal
);
9100 po
->po_ReadySigTask
= NULL
;
9101 //FreeSignal(po->po_ReadySignal);
9104 psdAddErrorMsg0(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
), "PoPo kicks ass.");
9107 if((cfgchanged
+ 2) == counter
)
9109 KPRINTF(10, ("Sending information about config changed to all classes.\n"));
9110 /* Inform all classes */
9112 puc
= (struct PsdUsbClass
*) ps
->ps_Classes
.lh_Head
;
9113 while(puc
->puc_Node
.ln_Succ
)
9115 usbDoMethod(UCM_ConfigChangedEvent
);
9116 puc
= (struct PsdUsbClass
*) puc
->puc_Node
.ln_Succ
;
9121 // power saving stuff, check every second
9122 if((counter
& 1) && ps
->ps_GlobalCfg
->pgc_PowerSaving
)
9124 struct PsdDevice
*pd
= NULL
;
9125 struct PsdInterface
*pif
;
9126 GetSysTime((APTR
) &currtime
);
9127 while((pd
= psdGetNextDevice(pd
)))
9129 if((pd
->pd_DevClass
!= HUB_CLASSCODE
) &&
9130 ((pd
->pd_Flags
& (PDFF_CONFIGURED
|PDFF_DEAD
|PDFF_SUSPENDED
|PDFF_APPBINDING
|PDFF_DELEXPUNGE
)) == PDFF_CONFIGURED
))
9132 if(pd
->pd_LastActivity
.tv_secs
&& ((currtime
.tv_secs
- pd
->pd_LastActivity
.tv_secs
) > ps
->ps_GlobalCfg
->pgc_SuspendTimeout
))
9136 if(!((pd
->pd_CurrentConfig
->pc_Attr
& USCAF_REMOTE_WAKEUP
) && ps
->ps_GlobalCfg
->pgc_ForceSuspend
))
9138 if(pd
->pd_DevBinding
&& ((puc
= pd
->pd_ClsBinding
)))
9141 usbGetAttrs(UGA_CLASS
, NULL
, UCCA_SupportsSuspend
, &suspendable
, TAG_END
);
9147 pif
= (struct PsdInterface
*) pd
->pd_CurrentConfig
->pc_Interfaces
.lh_Head
;
9148 while(pif
->pif_Node
.ln_Succ
)
9150 if(pif
->pif_IfBinding
&& ((puc
= pif
->pif_ClsBinding
)))
9153 usbGetAttrs(UGA_CLASS
, NULL
, UCCA_SupportsSuspend
, &suspendable
, TAG_END
);
9160 pif
= (struct PsdInterface
*) pif
->pif_Node
.ln_Succ
;
9165 psdAddErrorMsg(RETURN_OK
, (STRPTR
) GM_UNIQUENAME(libname
), "Suspending '%s'.", pd
->pd_ProductStr
);
9166 psdSuspendDevice(pd
);
9168 pd
->pd_LastActivity
.tv_secs
= 0;
9174 sigs
= Wait(sigmask
);
9175 } while(!(sigs
& SIGBREAKF_CTRL_C
));
9176 psdRemEventHandler(ph
->ph_EventHandler
);
9177 ph
->ph_EventHandler
= NULL
;
9178 AbortIO(&ph
->ph_TimerIOReq
->tr_node
);
9179 WaitIO(&ph
->ph_TimerIOReq
->tr_node
);
9181 CloseDevice((struct IORequest
*) ph
->ph_TimerIOReq
);
9183 DeleteIORequest((struct IORequest
*) ph
->ph_TimerIOReq
);
9185 DeleteMsgPort(ph
->ph_TimerMsgPort
);
9187 DeleteMsgPort(ph
->ph_MsgPort
);
9188 ph
->ph_MsgPort
= NULL
;
9192 if(ph
->ph_ReadySigTask
)
9194 Signal(ph
->ph_ReadySigTask
, 1L<<ph
->ph_ReadySignal
);
9200 /*****************************************************************/
9202 /* /// "Packtables for psdGetAttrs() and psdSetAttrs() " */
9203 /* Pack table for PsdBase */
9204 static const ULONG PsdBasePT
[] =
9206 PACK_STARTTABLE(PA_Dummy
),
9207 PACK_ENTRY(PA_Dummy
, PA_ConfigRead
, PsdBase
, ps_ConfigRead
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9208 PACK_ENTRY(PA_Dummy
, PA_GlobalConfig
, PsdBase
, ps_GlobalCfg
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9209 PACK_ENTRY(PA_Dummy
, PA_MemPoolUsage
, PsdBase
, ps_MemAllocated
, PKCTRL_ULONG
|PKCTRL_UNPACKONLY
),
9210 PACK_ENTRY(PA_Dummy
, PA_CurrConfigHash
, PsdBase
, ps_ConfigHash
, PKCTRL_ULONG
|PKCTRL_UNPACKONLY
),
9211 PACK_ENTRY(PA_Dummy
, PA_SavedConfigHash
, PsdBase
, ps_SavedConfigHash
, PKCTRL_ULONG
|PKCTRL_PACKUNPACK
),
9212 PACK_ENTRY(PA_Dummy
, PA_ReleaseVersion
, PsdBase
, ps_ReleaseVersion
, PKCTRL_ULONG
|PKCTRL_UNPACKONLY
),
9213 PACK_ENTRY(PA_Dummy
, PA_OSVersion
, PsdBase
, ps_OSVersion
, PKCTRL_ULONG
|PKCTRL_UNPACKONLY
),
9217 /* Pack table for PsdErrorMsg */
9218 static const ULONG PsdErrorMsgPT
[] =
9220 PACK_STARTTABLE(EMA_Dummy
),
9221 PACK_ENTRY(EMA_Dummy
, EMA_Level
, PsdErrorMsg
, pem_Level
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9222 PACK_ENTRY(EMA_Dummy
, EMA_Origin
, PsdErrorMsg
, pem_Origin
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9223 PACK_ENTRY(EMA_Dummy
, EMA_Msg
, PsdErrorMsg
, pem_Msg
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9227 /* Pack table for PsdUsbClass */
9228 static const ULONG PsdUsbClassPT
[] =
9230 PACK_STARTTABLE(UCA_Dummy
),
9231 PACK_ENTRY(UCA_Dummy
, UCA_ClassBase
, PsdUsbClass
, puc_ClassBase
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9232 PACK_ENTRY(UCA_Dummy
, UCA_ClassName
, PsdUsbClass
, puc_ClassName
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9233 PACK_ENTRY(UCA_Dummy
, UCA_FullPath
, PsdUsbClass
, puc_FullPath
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9234 PACK_ENTRY(UCA_Dummy
, UCA_UseCount
, PsdUsbClass
, puc_UseCnt
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9238 /* Pack table for PsdHardware */
9239 static const ULONG PsdHardwarePT
[] =
9241 PACK_STARTTABLE(HA_Dummy
),
9242 PACK_ENTRY(HA_Dummy
, HA_DeviceName
, PsdHardware
, phw_DevName
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9243 PACK_ENTRY(HA_Dummy
, HA_DeviceUnit
, PsdHardware
, phw_Unit
, PKCTRL_ULONG
|PKCTRL_UNPACKONLY
),
9244 PACK_ENTRY(HA_Dummy
, HA_ProductName
, PsdHardware
, phw_ProductName
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9245 PACK_ENTRY(HA_Dummy
, HA_Manufacturer
, PsdHardware
, phw_Manufacturer
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9246 PACK_ENTRY(HA_Dummy
, HA_Description
, PsdHardware
, phw_Description
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9247 PACK_ENTRY(HA_Dummy
, HA_Copyright
, PsdHardware
, phw_Copyright
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9248 PACK_ENTRY(HA_Dummy
, HA_Version
, PsdHardware
, phw_Version
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9249 PACK_ENTRY(HA_Dummy
, HA_Revision
, PsdHardware
, phw_Revision
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9250 PACK_ENTRY(HA_Dummy
, HA_DriverVersion
, PsdHardware
, phw_DriverVers
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9254 /* Pack table for PsdDevice */
9255 static const ULONG PsdDevicePT
[] =
9257 PACK_STARTTABLE(DA_Dummy
),
9258 PACK_ENTRY(DA_Dummy
, DA_Address
, PsdDevice
, pd_DevAddr
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9259 PACK_ENTRY(DA_Dummy
, DA_NumConfigs
, PsdDevice
, pd_NumCfgs
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9260 PACK_ENTRY(DA_Dummy
, DA_CurrConfig
, PsdDevice
, pd_CurrCfg
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9261 PACK_ENTRY(DA_Dummy
, DA_Config
, PsdDevice
, pd_CurrentConfig
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9262 PACK_ENTRY(DA_Dummy
, DA_HubDevice
, PsdDevice
, pd_Hub
, PKCTRL_IPTR
|PKCTRL_PACKUNPACK
),
9263 PACK_ENTRY(DA_Dummy
, DA_UsbVersion
, PsdDevice
, pd_USBVers
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9264 PACK_ENTRY(DA_Dummy
, DA_Class
, PsdDevice
, pd_DevClass
, PKCTRL_WORD
|PKCTRL_UNPACKONLY
),
9265 PACK_ENTRY(DA_Dummy
, DA_SubClass
, PsdDevice
, pd_DevSubClass
, PKCTRL_WORD
|PKCTRL_UNPACKONLY
),
9266 PACK_ENTRY(DA_Dummy
, DA_Protocol
, PsdDevice
, pd_DevProto
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9267 PACK_ENTRY(DA_Dummy
, DA_VendorID
, PsdDevice
, pd_VendorID
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9268 PACK_ENTRY(DA_Dummy
, DA_MaxPktSize0
, PsdDevice
, pd_MaxPktSize0
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9269 PACK_ENTRY(DA_Dummy
, DA_ProductID
, PsdDevice
, pd_ProductID
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9270 PACK_ENTRY(DA_Dummy
, DA_Version
, PsdDevice
, pd_DevVers
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9271 PACK_ENTRY(DA_Dummy
, DA_Manufacturer
, PsdDevice
, pd_MnfctrStr
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9272 PACK_ENTRY(DA_Dummy
, DA_ProductName
, PsdDevice
, pd_ProductStr
, PKCTRL_IPTR
|PKCTRL_PACKUNPACK
),
9273 PACK_ENTRY(DA_Dummy
, DA_OrigProductName
, PsdDevice
, pd_OldProductStr
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9274 PACK_ENTRY(DA_Dummy
, DA_SerialNumber
, PsdDevice
, pd_SerNumStr
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9275 PACK_ENTRY(DA_Dummy
, DA_Hardware
, PsdDevice
, pd_Hardware
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9276 PACK_ENTRY(DA_Dummy
, DA_Binding
, PsdDevice
, pd_DevBinding
, PKCTRL_IPTR
|PKCTRL_PACKUNPACK
),
9277 PACK_ENTRY(DA_Dummy
, DA_BindingClass
, PsdDevice
, pd_ClsBinding
, PKCTRL_IPTR
|PKCTRL_PACKUNPACK
),
9278 PACK_ENTRY(DA_Dummy
, DA_LangIDArray
, PsdDevice
, pd_LangIDArray
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9279 PACK_ENTRY(DA_Dummy
, DA_CurrLangID
, PsdDevice
, pd_CurrLangID
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9280 PACK_ENTRY(DA_Dummy
, DA_IDString
, PsdDevice
, pd_IDString
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9281 PACK_ENTRY(DA_Dummy
, DA_CloneCount
, PsdDevice
, pd_CloneCount
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9282 PACK_ENTRY(DA_Dummy
, DA_AtHubPortNumber
, PsdDevice
, pd_HubPort
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9283 PACK_ENTRY(DA_Dummy
, DA_PowerDrained
, PsdDevice
, pd_PowerDrain
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9284 PACK_ENTRY(DA_Dummy
, DA_PowerSupply
, PsdDevice
, pd_PowerSupply
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9285 PACK_ENTRY(DA_Dummy
, DA_IsNewToMe
, PsdDevice
, pd_IsNewToMe
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9286 PACK_ENTRY(DA_Dummy
, DA_InhibitPopup
, PsdDevice
, pd_PoPoCfg
.poc_InhibitPopup
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9287 PACK_ENTRY(DA_Dummy
, DA_InhibitClassBind
, PsdDevice
, pd_PoPoCfg
.poc_NoClassBind
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9288 PACK_ENTRY(DA_Dummy
, DA_OverridePowerInfo
, PsdDevice
, pd_PoPoCfg
.poc_OverridePowerInfo
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9289 PACK_ENTRY(DA_Dummy
, DA_HubThinkTime
, PsdDevice
, pd_HubThinkTime
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9290 PACK_WORDBIT(DA_Dummy
, DA_IsLowspeed
, PsdDevice
, pd_Flags
, PKCTRL_BIT
|PKCTRL_PACKUNPACK
, PDFF_LOWSPEED
),
9291 PACK_WORDBIT(DA_Dummy
, DA_IsHighspeed
, PsdDevice
, pd_Flags
, PKCTRL_BIT
|PKCTRL_PACKUNPACK
, PDFF_HIGHSPEED
),
9292 PACK_WORDBIT(DA_Dummy
, DA_IsConnected
, PsdDevice
, pd_Flags
, PKCTRL_BIT
|PKCTRL_PACKUNPACK
, PDFF_CONNECTED
),
9293 PACK_WORDBIT(DA_Dummy
, DA_HasAddress
, PsdDevice
, pd_Flags
, PKCTRL_BIT
|PKCTRL_PACKUNPACK
, PDFF_HASDEVADDR
),
9294 PACK_WORDBIT(DA_Dummy
, DA_HasDevDesc
, PsdDevice
, pd_Flags
, PKCTRL_BIT
|PKCTRL_PACKUNPACK
, PDFF_HASDEVDESC
),
9295 PACK_WORDBIT(DA_Dummy
, DA_IsConfigured
, PsdDevice
, pd_Flags
, PKCTRL_BIT
|PKCTRL_PACKUNPACK
, PDFF_CONFIGURED
),
9296 PACK_WORDBIT(DA_Dummy
, DA_IsDead
, PsdDevice
, pd_Flags
, PKCTRL_BIT
|PKCTRL_UNPACKONLY
, PDFF_DEAD
),
9297 PACK_WORDBIT(DA_Dummy
, DA_IsSuspended
, PsdDevice
, pd_Flags
, PKCTRL_BIT
|PKCTRL_PACKUNPACK
, PDFF_SUSPENDED
),
9298 PACK_WORDBIT(DA_Dummy
, DA_HasAppBinding
, PsdDevice
, pd_Flags
, PKCTRL_BIT
|PKCTRL_UNPACKONLY
, PDFF_APPBINDING
),
9299 PACK_WORDBIT(DA_Dummy
, DA_NeedsSplitTrans
, PsdDevice
, pd_Flags
, PKCTRL_BIT
|PKCTRL_PACKUNPACK
, PDFF_NEEDSSPLIT
),
9300 PACK_WORDBIT(DA_Dummy
, DA_LowPower
, PsdDevice
, pd_Flags
, PKCTRL_BIT
|PKCTRL_UNPACKONLY
, PDFF_LOWPOWER
),
9301 #ifdef AROS_USB30_CODE
9302 PACK_WORDBIT(DA_Dummy
, DA_IsSuperspeed
, PsdDevice
, pd_Flags
, PKCTRL_BIT
|PKCTRL_PACKUNPACK
, PDFF_SUPERSPEED
),
9307 /* Pack table for PsdConfig */
9308 static const ULONG PsdConfigPT
[] =
9310 PACK_STARTTABLE(CA_Dummy
),
9311 PACK_ENTRY(CA_Dummy
, CA_ConfigNum
, PsdConfig
, pc_CfgNum
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9312 PACK_ENTRY(CA_Dummy
, CA_MaxPower
, PsdConfig
, pc_MaxPower
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9313 PACK_ENTRY(CA_Dummy
, CA_ConfigName
, PsdConfig
, pc_CfgStr
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9314 PACK_ENTRY(CA_Dummy
, CA_NumInterfaces
, PsdConfig
, pc_NumIfs
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9315 PACK_ENTRY(CA_Dummy
, CA_Attrs
, PsdConfig
, pc_Attr
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9316 PACK_ENTRY(CA_Dummy
, CA_Device
, PsdConfig
, pc_Device
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9317 PACK_WORDBIT(CA_Dummy
, CA_SelfPowered
, PsdConfig
, pc_Attr
, PKCTRL_BIT
|PKCTRL_PACKUNPACK
, USCAF_SELF_POWERED
),
9318 PACK_WORDBIT(CA_Dummy
, CA_RemoteWakeup
, PsdConfig
, pc_Attr
, PKCTRL_BIT
|PKCTRL_UNPACKONLY
, USCAF_REMOTE_WAKEUP
),
9322 /* Pack table for PsdDescriptor */
9323 static const ULONG PsdDescriptorPT
[] =
9325 PACK_STARTTABLE(DDA_Dummy
),
9326 PACK_ENTRY(DDA_Dummy
, DDA_Device
, PsdDescriptor
, pdd_Device
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9327 PACK_ENTRY(DDA_Dummy
, DDA_Config
, PsdDescriptor
, pdd_Config
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9328 PACK_ENTRY(DDA_Dummy
, DDA_Interface
, PsdDescriptor
, pdd_Interface
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9329 PACK_ENTRY(DDA_Dummy
, DDA_Endpoint
, PsdDescriptor
, pdd_Endpoint
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9330 PACK_ENTRY(DDA_Dummy
, DDA_Name
, PsdDescriptor
, pdd_Name
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9331 PACK_ENTRY(DDA_Dummy
, DDA_DescriptorType
, PsdDescriptor
, pdd_Type
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9332 PACK_ENTRY(DDA_Dummy
, DDA_CS_SubType
, PsdDescriptor
, pdd_CSSubType
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9333 PACK_ENTRY(DDA_Dummy
, DDA_DescriptorData
, PsdDescriptor
, pdd_Data
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9334 PACK_ENTRY(DDA_Dummy
, DDA_DescriptorLength
, PsdDescriptor
, pdd_Length
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9338 /* Pack table for PsdInterface */
9339 static const ULONG PsdInterfacePT
[] =
9341 PACK_STARTTABLE(IFA_Dummy
),
9342 PACK_ENTRY(IFA_Dummy
, IFA_InterfaceNum
, PsdInterface
, pif_IfNum
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9343 PACK_ENTRY(IFA_Dummy
, IFA_AlternateNum
, PsdInterface
, pif_Alternate
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9344 PACK_ENTRY(IFA_Dummy
, IFA_NumEndpoints
, PsdInterface
, pif_NumEPs
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9345 PACK_ENTRY(IFA_Dummy
, IFA_Class
, PsdInterface
, pif_IfClass
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9346 PACK_ENTRY(IFA_Dummy
, IFA_SubClass
, PsdInterface
, pif_IfSubClass
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9347 PACK_ENTRY(IFA_Dummy
, IFA_Protocol
, PsdInterface
, pif_IfProto
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9348 PACK_ENTRY(IFA_Dummy
, IFA_InterfaceName
, PsdInterface
, pif_IfStr
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9349 PACK_ENTRY(IFA_Dummy
, IFA_Config
, PsdInterface
, pif_Config
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9350 PACK_ENTRY(IFA_Dummy
, IFA_Binding
, PsdInterface
, pif_IfBinding
, PKCTRL_IPTR
|PKCTRL_PACKUNPACK
),
9351 PACK_ENTRY(IFA_Dummy
, IFA_BindingClass
, PsdInterface
, pif_ClsBinding
, PKCTRL_IPTR
|PKCTRL_PACKUNPACK
),
9352 PACK_ENTRY(IFA_Dummy
, IFA_IDString
, PsdInterface
, pif_IDString
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9356 /* Pack table for PsdEndpoint */
9357 static const ULONG PsdEndpointPT
[] =
9359 PACK_STARTTABLE(EA_Dummy
),
9360 PACK_ENTRY(EA_Dummy
, EA_EndpointNum
, PsdEndpoint
, pep_EPNum
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9361 PACK_ENTRY(EA_Dummy
, EA_TransferType
, PsdEndpoint
, pep_TransType
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9362 PACK_ENTRY(EA_Dummy
, EA_MaxPktSize
, PsdEndpoint
, pep_MaxPktSize
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9363 PACK_ENTRY(EA_Dummy
, EA_Interval
, PsdEndpoint
, pep_Interval
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9364 PACK_ENTRY(EA_Dummy
, EA_NumTransMuFrame
, PsdEndpoint
, pep_NumTransMuFr
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9365 PACK_ENTRY(EA_Dummy
, EA_SyncType
, PsdEndpoint
, pep_SyncType
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9366 PACK_ENTRY(EA_Dummy
, EA_UsageType
, PsdEndpoint
, pep_UsageType
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9367 PACK_ENTRY(EA_Dummy
, EA_Interface
, PsdEndpoint
, pep_Interface
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9368 PACK_WORDBIT(EA_Dummy
, EA_IsIn
, PsdEndpoint
, pep_Direction
, PKCTRL_BIT
|PKCTRL_UNPACKONLY
, 1),
9372 /* Pack table for PsdPipe */
9373 static const ULONG PsdPipePT
[] =
9375 PACK_STARTTABLE(PPA_Dummy
),
9376 PACK_ENTRY(PPA_Dummy
, PPA_Endpoint
, PsdPipe
, pp_Endpoint
, PKCTRL_IPTR
|PKCTRL_PACKUNPACK
),
9377 PACK_ENTRY(PPA_Dummy
, PPA_Error
, PsdPipe
, pp_IOReq
.iouh_Req
.io_Error
, PKCTRL_BYTE
|PKCTRL_UNPACKONLY
),
9378 PACK_ENTRY(PPA_Dummy
, PPA_Actual
, PsdPipe
, pp_IOReq
.iouh_Actual
, PKCTRL_ULONG
|PKCTRL_UNPACKONLY
),
9379 PACK_ENTRY(PPA_Dummy
, PPA_EndpointNum
, PsdPipe
, pp_IOReq
.iouh_Endpoint
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9380 PACK_ENTRY(PPA_Dummy
, PPA_DeviceAddress
, PsdPipe
, pp_IOReq
.iouh_DevAddr
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9381 PACK_ENTRY(PPA_Dummy
, PPA_MaxPktSize
, PsdPipe
, pp_IOReq
.iouh_MaxPktSize
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9382 PACK_ENTRY(PPA_Dummy
, PPA_NakTimeoutTime
, PsdPipe
, pp_IOReq
.iouh_NakTimeout
, PKCTRL_ULONG
|PKCTRL_PACKUNPACK
),
9383 PACK_ENTRY(PPA_Dummy
, PPA_Interval
, PsdPipe
, pp_IOReq
.iouh_Interval
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9384 PACK_WORDBIT(PPA_Dummy
, PPA_NoShortPackets
, PsdPipe
, pp_IOReq
.iouh_Flags
, PKCTRL_BIT
|PKCTRL_PACKUNPACK
, UHFF_NOSHORTPKT
),
9385 PACK_WORDBIT(PPA_Dummy
, PPA_NakTimeout
, PsdPipe
, pp_IOReq
.iouh_Flags
, PKCTRL_BIT
|PKCTRL_PACKUNPACK
, UHFF_NAKTIMEOUT
),
9386 PACK_WORDBIT(PPA_Dummy
, PPA_AllowRuntPackets
, PsdPipe
, pp_IOReq
.iouh_Flags
, PKCTRL_BIT
|PKCTRL_PACKUNPACK
, UHFF_ALLOWRUNTPKTS
),
9390 /* Pack table for PsdAppBinding */
9391 static const ULONG PsdAppBindingPT
[] =
9393 PACK_STARTTABLE(ABA_Dummy
),
9394 PACK_ENTRY(ABA_Dummy
, ABA_ReleaseHook
, PsdAppBinding
, pab_ReleaseHook
, PKCTRL_IPTR
|PKCTRL_PACKUNPACK
),
9395 PACK_ENTRY(ABA_Dummy
, ABA_Device
, PsdAppBinding
, pab_Device
, PKCTRL_IPTR
|PKCTRL_PACKUNPACK
),
9396 PACK_ENTRY(ABA_Dummy
, ABA_UserData
, PsdAppBinding
, pab_UserData
, PKCTRL_IPTR
|PKCTRL_PACKUNPACK
),
9397 PACK_ENTRY(ABA_Dummy
, ABA_Task
, PsdAppBinding
, pab_Task
, PKCTRL_IPTR
|PKCTRL_PACKUNPACK
),
9398 PACK_ENTRY(ABA_Dummy
, ABA_ForceRelease
, PsdAppBinding
, pab_ForceRelease
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9402 /* Pack table for PsdAppBinding */
9403 static const ULONG PsdEventNotePT
[] =
9405 PACK_STARTTABLE(ENA_Dummy
),
9406 PACK_ENTRY(ENA_Dummy
, ENA_EventID
, PsdEventNote
, pen_Event
, PKCTRL_UWORD
|PKCTRL_UNPACKONLY
),
9407 PACK_ENTRY(ENA_Dummy
, ENA_Param1
, PsdEventNote
, pen_Param1
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9408 PACK_ENTRY(ENA_Dummy
, ENA_Param2
, PsdEventNote
, pen_Param2
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9412 /* Pack table for PsdGlobalCfg */
9413 static const ULONG PsdGlobalCfgPT
[] =
9415 PACK_STARTTABLE(GCA_Dummy
),
9416 PACK_ENTRY(GCA_Dummy
, GCA_LogInfo
, PsdGlobalCfg
, pgc_LogInfo
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9417 PACK_ENTRY(GCA_Dummy
, GCA_LogWarning
, PsdGlobalCfg
, pgc_LogWarning
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9418 PACK_ENTRY(GCA_Dummy
, GCA_LogError
, PsdGlobalCfg
, pgc_LogError
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9419 PACK_ENTRY(GCA_Dummy
, GCA_LogFailure
, PsdGlobalCfg
, pgc_LogFailure
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9420 PACK_ENTRY(GCA_Dummy
, GCA_BootDelay
, PsdGlobalCfg
, pgc_BootDelay
, PKCTRL_ULONG
|PKCTRL_PACKUNPACK
),
9421 PACK_ENTRY(GCA_Dummy
, GCA_SubTaskPri
, PsdGlobalCfg
, pgc_SubTaskPri
, PKCTRL_WORD
|PKCTRL_PACKUNPACK
),
9422 PACK_ENTRY(GCA_Dummy
, GCA_PopupDeviceNew
, PsdGlobalCfg
, pgc_PopupDeviceNew
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9423 PACK_ENTRY(GCA_Dummy
, GCA_PopupDeviceGone
, PsdGlobalCfg
, pgc_PopupDeviceGone
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9424 PACK_ENTRY(GCA_Dummy
, GCA_PopupDeviceDeath
, PsdGlobalCfg
, pgc_PopupDeviceDeath
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9425 PACK_ENTRY(GCA_Dummy
, GCA_PopupCloseDelay
, PsdGlobalCfg
, pgc_PopupCloseDelay
, PKCTRL_ULONG
|PKCTRL_PACKUNPACK
),
9426 PACK_ENTRY(GCA_Dummy
, GCA_PopupActivateWin
, PsdGlobalCfg
, pgc_PopupActivateWin
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9427 PACK_ENTRY(GCA_Dummy
, GCA_PopupWinToFront
, PsdGlobalCfg
, pgc_PopupWinToFront
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9428 PACK_ENTRY(GCA_Dummy
, GCA_AutoDisableLP
, PsdGlobalCfg
, pgc_AutoDisableLP
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9429 PACK_ENTRY(GCA_Dummy
, GCA_AutoDisableDead
, PsdGlobalCfg
, pgc_AutoDisableDead
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9430 PACK_ENTRY(GCA_Dummy
, GCA_AutoRestartDead
, PsdGlobalCfg
, pgc_AutoRestartDead
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9431 PACK_ENTRY(GCA_Dummy
, GCA_PowerSaving
, PsdGlobalCfg
, pgc_PowerSaving
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9432 PACK_ENTRY(GCA_Dummy
, GCA_ForceSuspend
, PsdGlobalCfg
, pgc_ForceSuspend
, PKCTRL_UWORD
|PKCTRL_PACKUNPACK
),
9433 PACK_ENTRY(GCA_Dummy
, GCA_SuspendTimeout
, PsdGlobalCfg
, pgc_SuspendTimeout
, PKCTRL_ULONG
|PKCTRL_PACKUNPACK
),
9434 PACK_ENTRY(GCA_Dummy
, GCA_PrefsVersion
, PsdGlobalCfg
, pgc_PrefsVersion
, PKCTRL_ULONG
|PKCTRL_PACKUNPACK
),
9438 /* Pack table for PsdPipeStream */
9439 static const ULONG PsdPipeStreamPT
[] =
9441 PACK_STARTTABLE(PSA_Dummy
),
9442 PACK_ENTRY(PSA_Dummy
, PSA_MessagePort
, PsdPipeStream
, pps_MsgPort
, PKCTRL_IPTR
|PKCTRL_PACKUNPACK
),
9443 PACK_ENTRY(PSA_Dummy
, PSA_NumPipes
, PsdPipeStream
, pps_NumPipes
, PKCTRL_ULONG
|PKCTRL_PACKUNPACK
),
9444 PACK_ENTRY(PSA_Dummy
, PSA_BufferSize
, PsdPipeStream
, pps_BufferSize
, PKCTRL_ULONG
|PKCTRL_PACKUNPACK
),
9445 PACK_ENTRY(PSA_Dummy
, PSA_NakTimeoutTime
, PsdPipeStream
, pps_NakTimeoutTime
, PKCTRL_ULONG
|PKCTRL_PACKUNPACK
),
9446 PACK_ENTRY(PSA_Dummy
, PSA_BytesPending
, PsdPipeStream
, pps_BytesPending
, PKCTRL_ULONG
|PKCTRL_UNPACKONLY
),
9447 PACK_ENTRY(PSA_Dummy
, PSA_Error
, PsdPipeStream
, pps_Error
, PKCTRL_LONG
|PKCTRL_PACKUNPACK
),
9448 PACK_ENTRY(PSA_Dummy
, PSA_TermArray
, PsdPipeStream
, pps_TermArray
, PKCTRL_IPTR
|PKCTRL_PACKUNPACK
),
9449 PACK_ENTRY(PSA_Dummy
, PSA_AbortSigMask
, PsdPipeStream
, pps_AbortSigMask
, PKCTRL_ULONG
|PKCTRL_PACKUNPACK
),
9450 PACK_ENTRY(PSA_Dummy
, PSA_ActivePipe
, PsdPipeStream
, pps_ActivePipe
, PKCTRL_IPTR
|PKCTRL_UNPACKONLY
),
9451 PACK_WORDBIT(PSA_Dummy
, PSA_AsyncIO
, PsdPipeStream
, pps_Flags
, PKCTRL_BIT
|PKCTRL_PACKUNPACK
, PSFF_ASYNCIO
),
9452 PACK_WORDBIT(PSA_Dummy
, PSA_ShortPktTerm
, PsdPipeStream
, pps_Flags
, PKCTRL_BIT
|PKCTRL_PACKUNPACK
, PSFF_SHORTTERM
),
9453 PACK_WORDBIT(PSA_Dummy
, PSA_ReadAhead
, PsdPipeStream
, pps_Flags
, PKCTRL_BIT
|PKCTRL_PACKUNPACK
, PSFF_READAHEAD
),
9454 PACK_WORDBIT(PSA_Dummy
, PSA_BufferedRead
, PsdPipeStream
, pps_Flags
, PKCTRL_BIT
|PKCTRL_PACKUNPACK
, PSFF_BUFFERREAD
),
9455 PACK_WORDBIT(PSA_Dummy
, PSA_BufferedWrite
, PsdPipeStream
, pps_Flags
, PKCTRL_BIT
|PKCTRL_PACKUNPACK
, PSFF_BUFFERWRITE
),
9456 PACK_WORDBIT(PSA_Dummy
, PSA_NoZeroPktTerm
, PsdPipeStream
, pps_Flags
, PKCTRL_BIT
|PKCTRL_PACKUNPACK
, PSFF_NOSHORTPKT
),
9457 PACK_WORDBIT(PSA_Dummy
, PSA_NakTimeout
, PsdPipeStream
, pps_Flags
, PKCTRL_BIT
|PKCTRL_PACKUNPACK
, PSFF_NAKTIMEOUT
),
9458 PACK_WORDBIT(PSA_Dummy
, PSA_AllowRuntPackets
, PsdPipeStream
, pps_Flags
, PKCTRL_BIT
|PKCTRL_PACKUNPACK
, PSFF_ALLOWRUNT
),
9459 PACK_WORDBIT(PSA_Dummy
, PSA_DoNotWait
, PsdPipeStream
, pps_Flags
, PKCTRL_BIT
|PKCTRL_PACKUNPACK
, PSFF_DONOTWAIT
),
9463 /* Pack table for PsdRTIsoHandler */
9464 static const ULONG PsdRTIsoHandlerPT
[] =
9466 PACK_STARTTABLE(RTA_Dummy
),
9467 PACK_ENTRY(RTA_Dummy
, RTA_InRequestHook
, PsdRTIsoHandler
, prt_RTIso
.urti_InReqHook
, PKCTRL_IPTR
|PKCTRL_PACKUNPACK
),
9468 PACK_ENTRY(RTA_Dummy
, RTA_OutRequestHook
, PsdRTIsoHandler
, prt_RTIso
.urti_OutReqHook
, PKCTRL_IPTR
|PKCTRL_PACKUNPACK
),
9469 PACK_ENTRY(RTA_Dummy
, RTA_InDoneHook
, PsdRTIsoHandler
, prt_RTIso
.urti_InDoneHook
, PKCTRL_IPTR
|PKCTRL_PACKUNPACK
),
9470 PACK_ENTRY(RTA_Dummy
, RTA_OutDoneHook
, PsdRTIsoHandler
, prt_RTIso
.urti_OutDoneHook
, PKCTRL_IPTR
|PKCTRL_PACKUNPACK
),
9471 PACK_ENTRY(RTA_Dummy
, RTA_ReleaseHook
, PsdRTIsoHandler
, prt_ReleaseHook
, PKCTRL_IPTR
|PKCTRL_PACKUNPACK
),
9472 PACK_ENTRY(RTA_Dummy
, RTA_OutPrefetchSize
, PsdRTIsoHandler
, prt_RTIso
.urti_OutPrefetch
, PKCTRL_ULONG
|PKCTRL_PACKUNPACK
),
9476 /* PGA assignment table */
9477 static const ULONG
*PsdPTArray
[] =