2 *----------------------------------------------------------------------------
3 * bluetooth class for poseidon
4 *----------------------------------------------------------------------------
5 * By Chris Hodges <chrisly@platon42.de>
10 #include "bluetooth.class.h"
13 static const STRPTR libname
= MOD_NAME_STRING
;
16 const APTR DevFuncTable
[] =
18 &AROS_SLIB_ENTRY(devOpen
, dev
, 1),
19 &AROS_SLIB_ENTRY(devClose
, dev
, 2),
20 &AROS_SLIB_ENTRY(devExpunge
, dev
, 3),
21 &AROS_SLIB_ENTRY(devReserved
, dev
, 4),
22 &AROS_SLIB_ENTRY(devBeginIO
, dev
, 5),
23 &AROS_SLIB_ENTRY(devAbortIO
, dev
, 6),
27 static int libInit(LIBBASETYPEPTR nh
)
29 struct NepClassBT
*ncp
;
30 struct NepBTBase
*ret
= NULL
;
32 KPRINTF(10, ("libInit nh: 0x%08lx SysBase: 0x%08lx\n", nh
, SysBase
));
34 nh
->nh_UtilityBase
= OpenLibrary("utility.library", 39);
36 #define UtilityBase nh->nh_UtilityBase
40 NewList(&nh
->nh_Units
);
41 nh
->nh_MemPool
= CreatePool(MEMF_PUBLIC
|MEMF_CLEAR
, 32*1024, sizeof(struct BTHCIEventMsg
));
44 if((nh
->nh_DevBase
= (struct NepBTDevBase
*) MakeLibrary((APTR
) DevFuncTable
, NULL
, (APTR
) devInit
,
45 sizeof(struct NepBTDevBase
), NULL
)))
48 ncp
= &nh
->nh_DummyNCP
;
49 ncp
->ncp_ClsBase
= nh
;
50 ncp
->ncp_Interface
= NULL
;
51 ncp
->ncp_CDC
= AllocVec(sizeof(struct ClsDevCfg
), MEMF_PUBLIC
|MEMF_CLEAR
);
54 nh
->nh_DevBase
->np_ClsBase
= nh
;
56 AddDevice((struct Device
*) nh
->nh_DevBase
);
57 nh
->nh_DevBase
->np_Library
.lib_OpenCnt
++;
62 DeletePool(nh
->nh_MemPool
);
63 KPRINTF(20, ("failed to create usbbluetooth.device\n"));
68 CloseLibrary(UtilityBase
);
71 KPRINTF(20, ("libInit: OpenLibrary(\"utility.library\", 39) failed!\n"));
74 KPRINTF(10, ("libInit: Ok\n"));
75 return(ret
? TRUE
: FALSE
);
78 static int libOpen(LIBBASETYPEPTR nh
)
80 KPRINTF(10, ("libOpen nh: 0x%08lx\n", nh
));
85 static int libExpunge(LIBBASETYPEPTR nh
)
87 struct NepClassBT
*ncp
;
89 KPRINTF(10, ("libExpunge nh: 0x%08lx\n", nh
));
91 if(nh
->nh_DevBase
->np_Library
.lib_OpenCnt
== 1)
93 KPRINTF(1, ("libExpunge: closelibrary utilitybase 0x%08lx\n",
95 CloseLibrary((struct Library
*) UtilityBase
);
97 ncp
= (struct NepClassBT
*) nh
->nh_Units
.lh_Head
;
98 while(ncp
->ncp_Unit
.unit_MsgPort
.mp_Node
.ln_Succ
)
100 Remove((struct Node
*) ncp
);
101 FreeVec(ncp
->ncp_CDC
);
103 ncp
= (struct NepClassBT
*) nh
->nh_Units
.lh_Head
;
107 DeletePool(nh
->nh_MemPool
);
110 nh
->nh_DevBase
->np_Library
.lib_OpenCnt
--;
111 RemDevice((struct Device
*) nh
->nh_DevBase
);
112 KPRINTF(5, ("libExpunge: Unloading done! bluetooth.class expunged!\n\n"));
114 KPRINTF(5, ("libExpunge: Could not expunge, LIBF_DELEXP set!\n"));
121 ADD2INITLIB(libInit
, 0)
122 ADD2OPENLIB(libOpen
, 0)
123 ADD2EXPUNGELIB(libExpunge
, 0)
127 * ***********************************************************************
128 * * Library functions *
129 * ***********************************************************************
132 /* /// "usbAttemptInterfaceBinding()" */
133 struct NepClassBT
* usbAttemptInterfaceBinding(struct NepBTBase
*nh
, struct PsdInterface
*pif
)
140 KPRINTF(1, ("nepBTAttemptInterfaceBinding(%08lx)\n", pif
));
141 if((ps
= OpenLibrary("poseidon.library", 4)))
143 psdGetAttrs(PGA_INTERFACE
, pif
,
145 IFA_SubClass
, &subclass
,
146 IFA_Protocol
, &proto
,
149 if((ifclass
== BLUETOOTH_CLASSCODE
) &&
150 (subclass
== BLUETOOTH_RF_SUBCLASS
) &&
151 (proto
== BLUETOOTH_PROTO_PRG
))
156 aclin
= psdFindEndpoint(pif
, NULL
,
158 EA_TransferType
, USEAF_BULK
,
160 aclout
= psdFindEndpoint(pif
, NULL
,
162 EA_TransferType
, USEAF_BULK
,
164 eventint
= psdFindEndpoint(pif
, NULL
,
166 EA_TransferType
, USEAF_INTERRUPT
,
168 if(aclin
&& aclout
&& eventint
)
170 return(usbForceInterfaceBinding(nh
, pif
));
178 /* /// "usbForceInterfaceBinding()" */
179 struct NepClassBT
* usbForceInterfaceBinding(struct NepBTBase
*nh
, struct PsdInterface
*pif
)
182 struct NepClassBT
*ncp
;
183 struct NepClassBT
*tmpncp
;
184 struct PsdConfig
*pc
;
185 struct PsdDevice
*pd
;
186 struct ClsDevCfg
*cdc
;
198 struct Task
*tmptask
;
200 KPRINTF(1, ("nepBTAttemptInterfaceBinding(%08lx)\n", pif
));
201 if((ps
= OpenLibrary("poseidon.library", 4)))
203 psdGetAttrs(PGA_INTERFACE
, pif
,
204 IFA_InterfaceNum
, &ifnum
,
205 IFA_AlternateNum
, &altifnum
,
206 IFA_IDString
, &ifidstr
,
209 psdGetAttrs(PGA_CONFIG
, pc
,
211 CA_ConfigNum
, &cfgnum
,
213 psdGetAttrs(PGA_DEVICE
, pd
,
214 DA_ProductID
, &prodid
,
215 DA_VendorID
, &vendid
,
216 DA_ProductName
, &devname
,
217 DA_IDString
, &devidstr
,
222 ncp
= (struct NepClassBT
*) nh
->nh_Units
.lh_Head
;
223 while(ncp
->ncp_Unit
.unit_MsgPort
.mp_Node
.ln_Succ
)
225 if((ncp
->ncp_UnitAltIfNum
== altifnum
) && (ncp
->ncp_UnitIfNum
== ifnum
) &&
226 (ncp
->ncp_UnitProdID
== prodid
) && (ncp
->ncp_UnitVendorID
== vendid
))
228 unitno
= ncp
->ncp_UnitNo
;
232 ncp
= (struct NepClassBT
*) ncp
->ncp_Unit
.unit_MsgPort
.mp_Node
.ln_Succ
;
236 /* as units are freed in the expunge-vector, the memory is
237 outside the scope of the poseidon library */
238 if(!(ncp
= AllocVec(sizeof(struct NepClassBT
), MEMF_PUBLIC
|MEMF_CLEAR
)))
244 ncp
->ncp_CDC
= cdc
= AllocVec(sizeof(struct ClsDevCfg
), MEMF_PUBLIC
|MEMF_CLEAR
);
252 /* IORequests may be queued even if the task is gone. */
253 ncp
->ncp_UnitNo
= (ULONG
) -1;
254 NewList(&ncp
->ncp_Unit
.unit_MsgPort
.mp_MsgList
);
255 NewList(&ncp
->ncp_ReadQueue
);
256 NewList(&ncp
->ncp_WriteQueue
);
257 AddTail(&nh
->nh_Units
, &ncp
->ncp_Unit
.unit_MsgPort
.mp_Node
);
259 ncp
->ncp_ClsBase
= nh
;
260 ncp
->ncp_Interface
= pif
;
261 ncp
->ncp_Device
= pd
;
262 ncp
->ncp_Config
= pc
;
263 ncp
->ncp_UnitAltIfNum
= altifnum
;
264 ncp
->ncp_UnitIfNum
= ifnum
;
265 ncp
->ncp_UnitCfgNum
= cfgnum
;
266 ncp
->ncp_UnitProdID
= prodid
;
267 ncp
->ncp_UnitVendorID
= vendid
;
268 ncp
->ncp_DevIDString
= devidstr
;
269 ncp
->ncp_IfIDString
= ifidstr
;
271 /* try to load default config */
272 nLoadBindingConfig(ncp
);
274 /* Find next free unit number */
275 if(unitno
== (ULONG
) -1)
277 unitno
= ncp
->ncp_CDC
->cdc_DefaultUnit
;
278 tmpncp
= (struct NepClassBT
*) nh
->nh_Units
.lh_Head
;
279 while(tmpncp
->ncp_Unit
.unit_MsgPort
.mp_Node
.ln_Succ
)
281 if(tmpncp
->ncp_UnitNo
== unitno
)
284 tmpncp
= (struct NepClassBT
*) nh
->nh_Units
.lh_Head
;
286 tmpncp
= (struct NepClassBT
*) tmpncp
->ncp_Unit
.unit_MsgPort
.mp_Node
.ln_Succ
;
290 ncp
->ncp_UnitNo
= unitno
;
293 psdSafeRawDoFmt(buf
, 64, "bluetooth.class<%08lx>", ncp
);
294 ncp
->ncp_ReadySignal
= SIGB_SINGLE
;
295 ncp
->ncp_ReadySigTask
= FindTask(NULL
);
296 SetSignal(0, SIGF_SINGLE
);
297 if((tmptask
= psdSpawnSubTask(buf
, nBTTask
, ncp
)))
299 psdBorrowLocksWait(tmptask
, 1UL<<ncp
->ncp_ReadySignal
);
302 ncp
->ncp_ReadySigTask
= NULL
;
303 //FreeSignal(ncp->ncp_ReadySignal);
304 psdAddErrorMsg(RETURN_OK
, (STRPTR
) libname
,
305 "I've got blue teeth with '%s' through %s unit %ld!",
306 devname
, nh
->nh_DevBase
->np_Library
.lib_Node
.ln_Name
,
313 ncp
->ncp_ReadySigTask
= NULL
;
314 //FreeSignal(ncp->ncp_ReadySignal);
315 /* Get rid of unit structure */
317 Remove((struct Node *) ncp);
318 FreeVec(ncp->ncp_CDC);
327 /* /// "usbReleaseInterfaceBinding()" */
328 void usbReleaseInterfaceBinding(struct NepBTBase
*nh
, struct NepClassBT
*ncp
)
333 KPRINTF(1, ("nepBTReleaseInterfaceBinding(%08lx)\n", ncp
));
334 if((ps
= OpenLibrary("poseidon.library", 4)))
337 ncp
->ncp_ReadySignal
= SIGB_SINGLE
;
338 ncp
->ncp_ReadySigTask
= FindTask(NULL
);
341 Signal(ncp
->ncp_Task
, SIGBREAKF_CTRL_C
);
346 Wait(1UL<<ncp
->ncp_ReadySignal
);
348 //FreeSignal(ncp->ncp_ReadySignal);
349 psdGetAttrs(PGA_DEVICE
, ncp
->ncp_Device
, DA_ProductName
, &devname
, TAG_END
);
350 psdAddErrorMsg(RETURN_OK
, (STRPTR
) libname
,
351 "'%s' lost all its teeth.",
359 /* /// "usbGetAttrsA()" */
360 AROS_LH3(LONG
, usbGetAttrsA
,
361 AROS_LHA(ULONG
, type
, D0
),
362 AROS_LHA(APTR
, usbstruct
, A0
),
363 AROS_LHA(struct TagItem
*, tags
, A1
),
364 LIBBASETYPEPTR
, nh
, 5, nep
)
371 KPRINTF(1, ("nepBTGetAttrsA(%ld, %08lx, %08lx)\n", type
, usbstruct
, tags
));
375 if((ti
= FindTagItem(UCCA_Priority
, tags
)))
377 *((SIPTR
*) ti
->ti_Data
) = 0;
380 if((ti
= FindTagItem(UCCA_Description
, tags
)))
382 *((STRPTR
*) ti
->ti_Data
) = "Bluetooth HCI via usbbluetooth.device";
385 if((ti
= FindTagItem(UCCA_HasClassCfgGUI
, tags
)))
387 *((IPTR
*) ti
->ti_Data
) = TRUE
;
390 if((ti
= FindTagItem(UCCA_HasBindingCfgGUI
, tags
)))
392 *((IPTR
*) ti
->ti_Data
) = TRUE
;
395 if((ti
= FindTagItem(UCCA_AfterDOSRestart
, tags
)))
397 *((IPTR
*) ti
->ti_Data
) = FALSE
;
400 if((ti
= FindTagItem(UCCA_UsingDefaultCfg
, tags
)))
402 *((IPTR
*) ti
->ti_Data
) = nh
->nh_DummyNCP
.ncp_UsingDefaultCfg
;
408 if((ti
= FindTagItem(UCBA_UsingDefaultCfg
, tags
)))
410 *((IPTR
*) ti
->ti_Data
) = ((struct NepClassBT
*) usbstruct
)->ncp_UsingDefaultCfg
;
420 /* /// "usbSetAttrsA()" */
421 AROS_LH3(LONG
, usbSetAttrsA
,
422 AROS_LHA(ULONG
, type
, D0
),
423 AROS_LHA(APTR
, usbstruct
, A0
),
424 AROS_LHA(struct TagItem
*, tags
, A1
),
425 LIBBASETYPEPTR
, nh
, 6, nep
)
433 /* /// "usbDoMethodA()" */
434 AROS_LH2(IPTR
, usbDoMethodA
,
435 AROS_LHA(ULONG
, methodid
, D0
),
436 AROS_LHA(IPTR
*, methoddata
, A1
),
437 LIBBASETYPEPTR
, nh
, 7, nep
)
441 struct NepClassBT
*ncp
;
443 KPRINTF(10, ("Do Method %ld\n", methodid
));
446 case UCM_AttemptInterfaceBinding
:
447 return((IPTR
) usbAttemptInterfaceBinding(nh
, (struct PsdInterface
*) methoddata
[0]));
449 case UCM_ForceInterfaceBinding
:
450 return((IPTR
) usbForceInterfaceBinding(nh
, (struct PsdInterface
*) methoddata
[0]));
452 case UCM_ReleaseInterfaceBinding
:
453 usbReleaseInterfaceBinding(nh
, (struct NepClassBT
*) methoddata
[0]);
456 case UCM_OpenCfgWindow
:
457 return(nOpenBindingCfgWindow(nh
, &nh
->nh_DummyNCP
));
459 case UCM_OpenBindingCfgWindow
:
460 return(nOpenBindingCfgWindow(nh
, (struct NepClassBT
*) methoddata
[0]));
462 case UCM_ConfigChangedEvent
:
463 nLoadClassConfig(nh
);
465 ncp
= (struct NepClassBT
*) nh
->nh_Units
.lh_Head
;
466 while(ncp
->ncp_Unit
.unit_MsgPort
.mp_Node
.ln_Succ
)
468 nLoadBindingConfig(ncp
);
469 ncp
= (struct NepClassBT
*) ncp
->ncp_Unit
.unit_MsgPort
.mp_Node
.ln_Succ
;
482 /* /// "nLoadClassConfig()" */
483 BOOL
nLoadClassConfig(struct NepBTBase
*nh
)
485 struct NepClassBT
*ncp
= &nh
->nh_DummyNCP
;
487 struct ClsDevCfg
*cdc
;
488 struct PsdIFFContext
*pic
;
490 KPRINTF(10, ("Loading Class Config...\n"));
495 if(!(ps
= OpenLibrary("poseidon.library", 4)))
501 /* Create default config */
502 ncp
->ncp_CDC
->cdc_ChunkID
= AROS_LONG2BE(MAKE_ID('B','T','H','P'));
503 ncp
->ncp_CDC
->cdc_Length
= AROS_LONG2BE(sizeof(struct ClsDevCfg
)-8);
504 ncp
->ncp_CDC
->cdc_DefaultUnit
= 0;
505 ncp
->ncp_CDC
->cdc_StackAuto
= TRUE
;
506 ncp
->ncp_UsingDefaultCfg
= TRUE
;
507 pic
= psdGetClsCfg(libname
);
510 cdc
= psdGetCfgChunk(pic
, AROS_LONG2BE(ncp
->ncp_CDC
->cdc_ChunkID
));
513 CopyMem(((UBYTE
*) cdc
) + 8, ((UBYTE
*) ncp
->ncp_CDC
) + 8, min(AROS_LONG2BE(cdc
->cdc_Length
), AROS_LONG2BE(ncp
->ncp_CDC
->cdc_Length
)));
515 ncp
->ncp_UsingDefaultCfg
= FALSE
;
524 /* /// "nLoadBindingConfig()" */
525 BOOL
nLoadBindingConfig(struct NepClassBT
*ncp
)
527 struct NepBTBase
*nh
= ncp
->ncp_ClsBase
;
529 struct ClsDevCfg
*cdc
;
530 struct PsdIFFContext
*pic
;
532 KPRINTF(10, ("Loading Binding Config...\n"));
537 //nLoadClassConfig(nh);
538 *ncp
->ncp_CDC
= *nh
->nh_DummyNCP
.ncp_CDC
;
539 ncp
->ncp_UsingDefaultCfg
= TRUE
;
541 if(!(ps
= OpenLibrary("poseidon.library", 4)))
548 pic
= psdGetUsbDevCfg(libname
, ncp
->ncp_DevIDString
, ncp
->ncp_IfIDString
);
551 cdc
= psdGetCfgChunk(pic
, AROS_LONG2BE(ncp
->ncp_CDC
->cdc_ChunkID
));
554 CopyMem(((UBYTE
*) cdc
) + 8, ((UBYTE
*) ncp
->ncp_CDC
) + 8, min(AROS_LONG2BE(cdc
->cdc_Length
), AROS_LONG2BE(ncp
->ncp_CDC
->cdc_Length
)));
556 ncp
->ncp_UsingDefaultCfg
= FALSE
;
565 /* /// "nOpenBindingCfgWindow()" */
566 LONG
nOpenBindingCfgWindow(struct NepBTBase
*nh
, struct NepClassBT
*ncp
)
569 KPRINTF(10, ("Opening GUI...\n"));
570 if(!(ps
= OpenLibrary("poseidon.library", 4)))
575 if(!ncp
->ncp_GUITask
)
577 if((ncp
->ncp_GUITask
= psdSpawnSubTask(MOD_NAME_STRING
" GUI", nGUITask
, ncp
)))
590 /**************************************************************************/
593 #define ps ncp->ncp_Base
595 /* /// "nIssueEventReq()" */
596 void nIssueEventReq(struct NepClassBT
*ncp
)
598 struct BTHCIEventMsg
*bem
;
599 bem
= (struct BTHCIEventMsg
*) GetMsg(ncp
->ncp_EventReplyPort
);
602 bem
= psdAllocVec(sizeof(struct BTHCIEventMsg
));
607 bem
->bem_Msg
.mn_ReplyPort
= ncp
->ncp_EventReplyPort
;
609 ncp
->ncp_EventsPending
--;
611 ncp
->ncp_CurrEventMsg
= bem
;
612 bem
->bem_Msg
.mn_Length
= 0;
613 psdSendPipe(ncp
->ncp_EPEventIntPipe
, &bem
->bem_Event
, ncp
->ncp_EPEventIntMaxPktSize
);
617 /* /// "nBTTask()" */
618 AROS_UFH0(void, nBTTask
)
622 struct NepClassBT
*ncp
;
627 struct IOBTHCIReq
*ioreq
;
628 struct IOBTHCIReq
*ioreq2
;
629 struct BTHCIEventMsg
*bem
;
632 if((ncp
= nAllocBT()))
635 if(ncp
->ncp_ReadySigTask
)
637 Signal(ncp
->ncp_ReadySigTask
, 1UL<<ncp
->ncp_ReadySignal
);
642 sigmask
= (1UL<<ncp
->ncp_Unit
.unit_MsgPort
.mp_SigBit
)|(1UL<<ncp
->ncp_TaskMsgPort
->mp_SigBit
)|SIGBREAKF_CTRL_C
;
643 KPRINTF(10, ("Unit Sigbit %ld\n", ncp
->ncp_Unit
.unit_MsgPort
.mp_SigBit
));
644 KPRINTF(10, ("Task Sigbit %ld\n", ncp
->ncp_TaskMsgPort
->mp_SigBit
));
647 if(!ncp
->ncp_CurrEventMsg
)
651 if(ncp
->ncp_AbortRead
)
653 ncp
->ncp_AbortRead
= FALSE
;
654 if(ncp
->ncp_ReadPending
)
656 psdAbortPipe(ncp
->ncp_EPACLInPipe
);
659 if(ncp
->ncp_AbortWrite
)
661 ncp
->ncp_AbortWrite
= FALSE
;
662 if(ncp
->ncp_WritePending
)
664 psdAbortPipe(ncp
->ncp_EPACLOutPipe
);
667 while((pp
= (struct PsdPipe
*) GetMsg(ncp
->ncp_TaskMsgPort
)))
669 KPRINTF(1, ("Pipe back %08lx\n", pp
));
670 if(pp
== ncp
->ncp_EPEventIntPipe
)
672 ioerr
= psdGetPipeError(pp
);
675 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) libname
,
676 "BT Event reception failed: %s (%ld)",
677 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
679 if((bem
= ncp
->ncp_CurrEventMsg
))
681 len
= psdGetPipeActual(pp
);
682 bem
->bem_Msg
.mn_Length
+= len
;
683 if(bem
->bem_Msg
.mn_Length
>= 2)
685 if(bem
->bem_Msg
.mn_Length
< bem
->bem_Event
.bhe_PayloadLength
+2)
687 // actually, this should not have been a short packet.
688 if(len
% ncp
->ncp_EPEventIntMaxPktSize
)
690 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) libname
,
691 "BT Event short packet (%ld < %ld)",
692 bem
->bem_Msg
.mn_Length
, bem
->bem_Event
.bhe_PayloadLength
+2);
694 // read remaining packet
695 psdSendPipe(ncp
->ncp_EPEventIntPipe
,
696 (((UBYTE
*) &bem
->bem_Event
.bhe_EventType
) + bem
->bem_Msg
.mn_Length
),
697 (ULONG
) bem
->bem_Event
.bhe_PayloadLength
+2 - bem
->bem_Msg
.mn_Length
);
699 if(bem
->bem_Msg
.mn_Length
> bem
->bem_Event
.bhe_PayloadLength
+2)
701 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) libname
,
702 "BT Event packet overflow (%ld > %ld)",
703 bem
->bem_Msg
.mn_Length
, bem
->bem_Event
.bhe_PayloadLength
+2);
705 /*psdAddErrorMsg(RETURN_OK, (STRPTR) libname,
706 "BT Event ready (%02lx: %ld)",
707 bem->bem_Event.bhe_EventType, bem->bem_Event.bhe_PayloadLength);*/
708 if(ncp
->ncp_EventMsgPort
)
710 PutMsg(ncp
->ncp_EventMsgPort
, &bem
->bem_Msg
);
712 PutMsg(ncp
->ncp_EventReplyPort
, &bem
->bem_Msg
);
714 ncp
->ncp_EventsPending
++;
715 ncp
->ncp_CurrEventMsg
= NULL
;
721 else if(pp
== ncp
->ncp_EPACLOutPipe
)
723 if((ioreq
= ncp
->ncp_WritePending
))
725 ioerr
= psdGetPipeError(pp
);
726 ioreq
->iobt_Actual
= psdGetPipeActual(pp
);
729 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) libname
,
730 "BT ACL transmit failed: %s (%ld)",
731 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
732 ioreq
->iobt_Req
.io_Error
= (ioerr
> 0) ? IOERR_BADLENGTH
: ioerr
;
734 ReplyMsg((struct Message
*) ioreq
);
735 ncp
->ncp_WritePending
= NULL
;
738 else if(pp
== ncp
->ncp_EPACLInPipe
)
740 if((ioreq
= ncp
->ncp_ReadPending
))
742 ioerr
= psdGetPipeError(pp
);
743 ioreq
->iobt_Actual
= psdGetPipeActual(pp
);
746 psdAddErrorMsg(RETURN_WARN
, (STRPTR
) libname
,
747 "BT ACL receive failed: %s (%ld)",
748 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
749 ioreq
->iobt_Req
.io_Error
= (ioerr
> 0) ? IOERR_BADLENGTH
: ioerr
;
751 ReplyMsg((struct Message
*) ioreq
);
753 ncp
->ncp_ReadPending
= NULL
;
757 while((ioreq
= (struct IOBTHCIReq
*) GetMsg(&ncp
->ncp_Unit
.unit_MsgPort
)))
759 KPRINTF(5, ("command ioreq: 0x%08lx cmd: %lu len: %ld\n",
760 ioreq
, ioreq
->iobt_Req
.io_Command
, ioreq
->iobt_Length
));
761 switch(ioreq
->iobt_Req
.io_Command
)
764 ioreq
->iobt_Actual
= 0;
766 AddTail(&ncp
->ncp_ReadQueue
, &ioreq
->iobt_Req
.io_Message
.mn_Node
);
771 ioreq
->iobt_Actual
= 0;
773 AddTail(&ncp
->ncp_WriteQueue
, &ioreq
->iobt_Req
.io_Message
.mn_Node
);
778 KPRINTF(10, ("WriteHCI: %04lx (%ld)\n",
779 *((UWORD
*) ioreq
->iobt_Data
), ((UBYTE
*) ioreq
->iobt_Data
)[2]));
780 psdPipeSetup(ncp
->ncp_EPCmdPipe
, URTF_CLASS
|URTF_DEVICE
,
782 ioreq
->iobt_Req
.io_Error
= psdDoPipe(ncp
->ncp_EPCmdPipe
, ioreq
->iobt_Data
, ioreq
->iobt_Length
);
783 ioreq
->iobt_Actual
= psdGetPipeActual(ncp
->ncp_EPCmdPipe
);
785 KPRINTF(10, ("Actual/Length: %ld\n", ioreq
->iobt_Actual
, ioreq
->iobt_Length
));
786 ReplyMsg((struct Message
*) ioreq
);
791 /* Reset does a flush too */
793 ioreq2
= (struct IOBTHCIReq
*) ncp
->ncp_WriteQueue
.lh_Head
;
794 while(ioreq2
->iobt_Req
.io_Message
.mn_Node
.ln_Succ
)
796 Remove((struct Node
*) ioreq2
);
797 ioreq2
->iobt_Req
.io_Error
= IOERR_ABORTED
;
798 ReplyMsg((struct Message
*) ioreq2
);
799 ioreq2
= (struct IOBTHCIReq
*) ncp
->ncp_WriteQueue
.lh_Head
;
801 ioreq2
= (struct IOBTHCIReq
*) ncp
->ncp_ReadQueue
.lh_Head
;
802 while(ioreq2
->iobt_Req
.io_Message
.mn_Node
.ln_Succ
)
804 Remove((struct Node
*) ioreq2
);
805 ioreq2
->iobt_Req
.io_Error
= IOERR_ABORTED
;
806 ReplyMsg((struct Message
*) ioreq2
);
807 ioreq2
= (struct IOBTHCIReq
*) ncp
->ncp_ReadQueue
.lh_Head
;
809 if((ioreq2
= ncp
->ncp_ReadPending
))
811 psdAbortPipe(ncp
->ncp_EPACLInPipe
);
812 psdWaitPipe(ncp
->ncp_EPACLInPipe
);
813 ioreq2
->iobt_Req
.io_Error
= IOERR_ABORTED
;
814 ReplyMsg((struct Message
*) ioreq2
);
815 ncp
->ncp_ReadPending
= NULL
;
817 if((ioreq2
= ncp
->ncp_WritePending
))
819 psdAbortPipe(ncp
->ncp_EPACLOutPipe
);
820 psdWaitPipe(ncp
->ncp_EPACLOutPipe
);
821 ioreq2
->iobt_Req
.io_Error
= IOERR_ABORTED
;
822 ReplyMsg((struct Message
*) ioreq2
);
823 ncp
->ncp_WritePending
= NULL
;
825 ReplyMsg((struct Message
*) ioreq
);
829 ioreq
->iobt_Req
.io_Error
= IOERR_NOCMD
;
830 ReplyMsg((struct Message
*) ioreq
);
834 ioreq
= (struct IOBTHCIReq
*) ncp
->ncp_WriteQueue
.lh_Head
;
835 if((!ncp
->ncp_WritePending
) && ioreq
->iobt_Req
.io_Message
.mn_Node
.ln_Succ
)
837 Remove((struct Node
*) ioreq
);
838 ncp
->ncp_WritePending
= ioreq
;
839 psdSendPipe(ncp
->ncp_EPACLOutPipe
, ioreq
->iobt_Data
, ioreq
->iobt_Length
);
841 ioreq
= (struct IOBTHCIReq
*) ncp
->ncp_ReadQueue
.lh_Head
;
842 if((!ncp
->ncp_ReadPending
) && ioreq
->iobt_Req
.io_Message
.mn_Node
.ln_Succ
)
844 Remove((struct Node
*) ioreq
);
845 ncp
->ncp_ReadPending
= ioreq
;
846 psdSendPipe(ncp
->ncp_EPACLInPipe
, ioreq
->iobt_Data
, ioreq
->iobt_Length
);
848 sigs
= Wait(sigmask
);
849 } while(!(sigs
& SIGBREAKF_CTRL_C
));
851 /* Now remove all requests still pending *anywhere* */
852 ncp
->ncp_DenyRequests
= TRUE
;
853 /* Current transfers */
854 if((ioreq
= ncp
->ncp_WritePending
))
856 KPRINTF(1, ("Aborting pending write...\n"));
857 psdAbortPipe(ncp
->ncp_EPACLOutPipe
);
858 psdWaitPipe(ncp
->ncp_EPACLOutPipe
);
859 ioreq
->iobt_Req
.io_Error
= IOERR_ABORTED
;
860 ReplyMsg((struct Message
*) ioreq
);
861 ncp
->ncp_WritePending
= NULL
;
863 if((ioreq
= ncp
->ncp_ReadPending
))
865 KPRINTF(1, ("Aborting pending read...\n"));
866 psdAbortPipe(ncp
->ncp_EPACLInPipe
);
867 psdWaitPipe(ncp
->ncp_EPACLInPipe
);
868 ioreq
->iobt_Req
.io_Error
= IOERR_ABORTED
;
869 ReplyMsg((struct Message
*) ioreq
);
870 ncp
->ncp_ReadPending
= NULL
;
872 if(ncp
->ncp_CurrEventMsg
)
874 KPRINTF(1, ("Aborting pending int...\n"));
875 psdAbortPipe(ncp
->ncp_EPEventIntPipe
);
876 psdWaitPipe(ncp
->ncp_EPEventIntPipe
);
877 psdFreeVec(ncp
->ncp_CurrEventMsg
);
878 ncp
->ncp_CurrEventMsg
= NULL
;
880 /* Read/Write queues */
881 ioreq
= (struct IOBTHCIReq
*) ncp
->ncp_WriteQueue
.lh_Head
;
882 while(ioreq
->iobt_Req
.io_Message
.mn_Node
.ln_Succ
)
884 KPRINTF(1, ("Removing write request...\n"));
885 Remove((struct Node
*) ioreq
);
886 ioreq
->iobt_Req
.io_Error
= IOERR_ABORTED
;
887 ReplyMsg((struct Message
*) ioreq
);
888 ioreq
= (struct IOBTHCIReq
*) ncp
->ncp_WriteQueue
.lh_Head
;
890 ioreq
= (struct IOBTHCIReq
*) ncp
->ncp_ReadQueue
.lh_Head
;
891 while(ioreq
->iobt_Req
.io_Message
.mn_Node
.ln_Succ
)
893 KPRINTF(1, ("Removing read request...\n"));
894 Remove((struct Node
*) ioreq
);
895 ioreq
->iobt_Req
.io_Error
= IOERR_ABORTED
;
896 ReplyMsg((struct Message
*) ioreq
);
897 ioreq
= (struct IOBTHCIReq
*) ncp
->ncp_ReadQueue
.lh_Head
;
900 while((ioreq
= (struct IOBTHCIReq
*) GetMsg(&ncp
->ncp_Unit
.unit_MsgPort
)))
902 KPRINTF(1, ("Aborting pending requests...\n"));
903 ioreq
->iobt_Req
.io_Error
= IOERR_ABORTED
;
904 ReplyMsg((struct Message
*) ioreq
);
907 KPRINTF(20, ("Going down the river!\n"));
915 /* /// "nAllocBT()" */
916 struct NepClassBT
* nAllocBT(void)
918 struct Task
*thistask
;
919 struct NepClassBT
*ncp
;
921 thistask
= FindTask(NULL
);
924 ncp
= thistask
->tc_UserData
;
925 if(!(ncp
->ncp_Base
= OpenLibrary("poseidon.library", 4)))
931 ncp
->ncp_EPACLIn
= psdFindEndpoint(ncp
->ncp_Interface
, NULL
,
933 EA_TransferType
, USEAF_BULK
,
935 ncp
->ncp_EPACLOut
= psdFindEndpoint(ncp
->ncp_Interface
, NULL
,
937 EA_TransferType
, USEAF_BULK
,
939 ncp
->ncp_EPEventInt
= psdFindEndpoint(ncp
->ncp_Interface
, NULL
,
941 EA_TransferType
, USEAF_INTERRUPT
,
944 if(!(ncp
->ncp_EPACLIn
&& ncp
->ncp_EPACLOut
&& ncp
->ncp_EPEventInt
))
946 psdAddErrorMsg(RETURN_FAIL
, (STRPTR
) libname
, "IN or OUT endpoint missing!");
950 psdGetAttrs(PGA_ENDPOINT
, ncp
->ncp_EPACLIn
,
951 EA_MaxPktSize
, &ncp
->ncp_EPACLInMaxPktSize
,
954 psdGetAttrs(PGA_ENDPOINT
, ncp
->ncp_EPEventInt
,
955 EA_MaxPktSize
, &ncp
->ncp_EPEventIntMaxPktSize
,
958 ncp
->ncp_Unit
.unit_MsgPort
.mp_SigBit
= AllocSignal(-1);
959 ncp
->ncp_Unit
.unit_MsgPort
.mp_SigTask
= thistask
;
960 ncp
->ncp_Unit
.unit_MsgPort
.mp_Node
.ln_Type
= NT_MSGPORT
;
961 ncp
->ncp_Unit
.unit_MsgPort
.mp_Flags
= PA_SIGNAL
;
963 if((ncp
->ncp_TaskMsgPort
= CreateMsgPort()))
965 if((ncp
->ncp_EventReplyPort
= CreateMsgPort()))
967 if((ncp
->ncp_EPCmdPipe
= psdAllocPipe(ncp
->ncp_Device
, ncp
->ncp_TaskMsgPort
, NULL
)))
969 /* Enable nak timeout */
970 psdSetAttrs(PGA_PIPE
, ncp
->ncp_EPCmdPipe
,
971 PPA_NakTimeout
, TRUE
,
972 PPA_NakTimeoutTime
, 5000,
974 if((ncp
->ncp_EPACLOutPipe
= psdAllocPipe(ncp
->ncp_Device
, ncp
->ncp_TaskMsgPort
, ncp
->ncp_EPACLOut
)))
976 /* Turn off short packets */
977 psdSetAttrs(PGA_PIPE
, ncp
->ncp_EPACLOutPipe
,
978 PPA_NoShortPackets
, TRUE
,
979 PPA_NakTimeout
, TRUE
,
980 PPA_NakTimeoutTime
, 5000,
982 if((ncp
->ncp_EPACLInPipe
= psdAllocPipe(ncp
->ncp_Device
, ncp
->ncp_TaskMsgPort
, ncp
->ncp_EPACLIn
)))
985 psdSetAttrs(PGA_PIPE
, ncp
->ncp_EPACLInPipe
,
986 PPA_NakTimeout
, FALSE
,
987 PPA_NakTimeoutTime
, 5000,
988 PPA_AllowRuntPackets
, TRUE
,
990 if((ncp
->ncp_EPEventIntPipe
= psdAllocPipe(ncp
->ncp_Device
, ncp
->ncp_TaskMsgPort
, ncp
->ncp_EPEventInt
)))
992 psdSetAttrs(PGA_PIPE
, ncp
->ncp_EPEventIntPipe
,
993 PPA_AllowRuntPackets
, TRUE
,
995 ncp
->ncp_Task
= thistask
;
998 psdFreePipe(ncp
->ncp_EPACLInPipe
);
1000 psdFreePipe(ncp
->ncp_EPACLOutPipe
);
1002 psdFreePipe(ncp
->ncp_EPCmdPipe
);
1004 DeleteMsgPort(ncp
->ncp_EventReplyPort
);
1006 DeleteMsgPort(ncp
->ncp_TaskMsgPort
);
1008 FreeSignal((LONG
) ncp
->ncp_Unit
.unit_MsgPort
.mp_SigBit
);
1010 CloseLibrary(ncp
->ncp_Base
);
1012 ncp
->ncp_Task
= NULL
;
1013 if(ncp
->ncp_ReadySigTask
)
1015 Signal(ncp
->ncp_ReadySigTask
, 1UL<<ncp
->ncp_ReadySignal
);
1021 /* /// "nFreeBT()" */
1022 void nFreeBT(struct NepClassBT
*ncp
)
1024 struct IOStdReq
*ioreq
;
1026 /* Disable the message port, messages may still be queued */
1027 ncp
->ncp_Unit
.unit_MsgPort
.mp_SigTask
= NULL
;
1028 ncp
->ncp_Unit
.unit_MsgPort
.mp_Flags
= PA_IGNORE
;
1029 FreeSignal((LONG
) ncp
->ncp_Unit
.unit_MsgPort
.mp_SigBit
);
1030 // get rid of all messages that still have appeared here
1031 while((ioreq
= (struct IOStdReq
*) GetMsg(&ncp
->ncp_Unit
.unit_MsgPort
)))
1033 ioreq
->io_Error
= IOERR_ABORTED
;
1034 ReplyMsg((struct Message
*) ioreq
);
1038 psdFreePipe(ncp
->ncp_EPCmdPipe
);
1039 psdFreePipe(ncp
->ncp_EPACLInPipe
);
1040 psdFreePipe(ncp
->ncp_EPACLOutPipe
);
1041 psdFreePipe(ncp
->ncp_EPEventIntPipe
);
1042 while(ncp
->ncp_EventsPending
)
1044 struct BTHCIEventMsg
*bem
;
1045 KPRINTF(10, ("%ld Events pending...", ncp
->ncp_EventsPending
));
1046 WaitPort(ncp
->ncp_EventReplyPort
);
1047 while((bem
= (struct BTHCIEventMsg
*) GetMsg(ncp
->ncp_EventReplyPort
)))
1050 ncp
->ncp_EventsPending
--;
1053 DeleteMsgPort(ncp
->ncp_EventReplyPort
);
1054 DeleteMsgPort(ncp
->ncp_TaskMsgPort
);
1055 CloseLibrary(ncp
->ncp_Base
);
1057 ncp
->ncp_Task
= NULL
;
1058 if(ncp
->ncp_ReadySigTask
)
1060 Signal(ncp
->ncp_ReadySigTask
, 1UL<<ncp
->ncp_ReadySignal
);
1065 /**************************************************************************/
1067 /* /// "nGUITask()" */
1068 AROS_UFH0(void, nGUITask
)
1072 struct Task
*thistask
;
1073 struct NepBTBase
*nh
;
1074 struct NepClassBT
*ncp
;
1075 struct PsdIFFContext
*pic
;
1077 thistask
= FindTask(NULL
);
1079 #define ps ncp->ncp_PsdBase
1080 #undef IntuitionBase
1081 #define IntuitionBase ncp->ncp_IntBase
1082 #undef MUIMasterBase
1083 #define MUIMasterBase ncp->ncp_MUIBase
1085 ncp
= thistask
->tc_UserData
;
1086 nh
= ncp
->ncp_ClsBase
;
1088 ++nh
->nh_Library
.lib_OpenCnt
;
1089 if(!(MUIMasterBase
= OpenLibrary(MUIMASTER_NAME
, MUIMASTER_VMIN
)))
1091 KPRINTF(10, ("Couldn't open muimaster.library.\n"));
1092 nGUITaskCleanup(ncp
);
1096 if(!(IntuitionBase
= OpenLibrary("intuition.library", 39)))
1098 KPRINTF(10, ("Couldn't open intuition.library.\n"));
1099 nGUITaskCleanup(ncp
);
1102 if(!(ps
= OpenLibrary("poseidon.library", 4)))
1104 KPRINTF(10, ("Couldn't open poseidon.library.\n"));
1105 nGUITaskCleanup(ncp
);
1109 ncp
->ncp_App
= ApplicationObject
,
1110 MUIA_Application_Title
, (IPTR
)libname
,
1111 MUIA_Application_Version
, (IPTR
)VERSION_STRING
,
1112 MUIA_Application_Copyright
, (IPTR
)"©2005-2009 Chris Hodges",
1113 MUIA_Application_Author
, (IPTR
)"Chris Hodges <chrisly@platon42.de>",
1114 MUIA_Application_Description
, (IPTR
)"Settings for the bluetooth.class",
1115 MUIA_Application_Base
, (IPTR
)"BLUETOOTH",
1116 MUIA_Application_HelpFile
, (IPTR
)"HELP:Poseidon.guide",
1117 MUIA_Application_Menustrip
, (IPTR
)MenustripObject
,
1118 Child
, (IPTR
)MenuObjectT((IPTR
)"Project"),
1119 Child
, (IPTR
)(ncp
->ncp_AboutMI
= MenuitemObject
,
1120 MUIA_Menuitem_Title
, (IPTR
)"About...",
1121 MUIA_Menuitem_Shortcut
, (IPTR
)"?",
1124 Child
, (IPTR
)MenuObjectT((IPTR
)"Settings"),
1125 Child
, (IPTR
)(ncp
->ncp_UseMI
= MenuitemObject
,
1126 MUIA_Menuitem_Title
, (IPTR
)"Save",
1127 MUIA_Menuitem_Shortcut
, (IPTR
)"S",
1129 Child
, (IPTR
)(ncp
->ncp_SetDefaultMI
= MenuitemObject
,
1130 MUIA_Menuitem_Title
, (IPTR
)"Save as Default",
1131 MUIA_Menuitem_Shortcut
, (IPTR
)"D",
1133 Child
, (IPTR
)MenuitemObject
,
1134 MUIA_Menuitem_Title
, (IPTR
)NM_BARLABEL
,
1136 Child
, (IPTR
)(ncp
->ncp_MUIPrefsMI
= MenuitemObject
,
1137 MUIA_Menuitem_Title
, (IPTR
)"MUI Settings",
1138 MUIA_Menuitem_Shortcut
, (IPTR
)"M",
1143 SubWindow
, (IPTR
)(ncp
->ncp_MainWindow
= WindowObject
,
1144 MUIA_Window_ID
, MAKE_ID('M','A','I','N'),
1145 MUIA_Window_Title
, (IPTR
)libname
,
1146 MUIA_HelpNode
, (IPTR
)libname
,
1148 WindowContents
, (IPTR
)VGroup
,
1149 Child
, (IPTR
)HGroup
, GroupFrameT((IPTR
)(ncp
->ncp_Interface
? "Device Settings" : "Default Device Settings")),
1150 Child
, (IPTR
)HSpace(0),
1151 Child
, (IPTR
)ColGroup(2),
1152 Child
, (IPTR
)Label((IPTR
) "Autostart BT Stack:"),
1153 Child
, (IPTR
)HGroup
,
1154 Child
, (IPTR
)(ncp
->ncp_StackAutoObj
= ImageObject
, ImageButtonFrame
,
1155 MUIA_Background
, MUII_ButtonBack
,
1157 MUIA_InputMode
, MUIV_InputMode_Toggle
,
1158 MUIA_Image_Spec
, MUII_CheckMark
,
1159 MUIA_Image_FreeVert
, TRUE
,
1160 MUIA_Selected
, ncp
->ncp_CDC
->cdc_StackAuto
,
1161 MUIA_ShowSelState
, FALSE
,
1163 Child
, (IPTR
)HSpace(0),
1165 Child
, (IPTR
)Label((IPTR
) "Default " DEVNAME
" Unit:"),
1166 Child
, (IPTR
)(ncp
->ncp_UnitObj
= StringObject
,
1169 MUIA_String_AdvanceOnCR
, TRUE
,
1170 MUIA_String_Integer
, ncp
->ncp_CDC
->cdc_DefaultUnit
,
1171 MUIA_String_Accept
, (IPTR
)"0123456789",
1176 Child
, (IPTR
)VSpace(0),
1177 Child
, (IPTR
)HGroup
,
1178 MUIA_Group_SameWidth
, TRUE
,
1179 Child
, (IPTR
)(ncp
->ncp_UseObj
= TextObject
, ButtonFrame
,
1180 MUIA_ShowMe
, (IPTR
)ncp
->ncp_Interface
,
1181 MUIA_Background
, MUII_ButtonBack
,
1183 MUIA_InputMode
, MUIV_InputMode_RelVerify
,
1184 MUIA_Text_Contents
, (IPTR
)"\33c Save ",
1186 Child
, (IPTR
)(ncp
->ncp_SetDefaultObj
= TextObject
, ButtonFrame
,
1187 MUIA_Background
, MUII_ButtonBack
,
1189 MUIA_InputMode
, MUIV_InputMode_RelVerify
,
1190 MUIA_Text_Contents
, (IPTR
)(ncp
->ncp_Interface
? "\33c Save as Default " : "\33c Save Defaults "),
1192 Child
, (IPTR
)(ncp
->ncp_CloseObj
= TextObject
, ButtonFrame
,
1193 MUIA_Background
, MUII_ButtonBack
,
1195 MUIA_InputMode
, MUIV_InputMode_RelVerify
,
1196 MUIA_Text_Contents
, (IPTR
)"\33c Use ",
1205 KPRINTF(10, ("Couldn't create application\n"));
1206 nGUITaskCleanup(ncp
);
1210 DoMethod(ncp
->ncp_MainWindow
, MUIM_Notify
, MUIA_Window_CloseRequest
, TRUE
,
1211 ncp
->ncp_App
, 2, MUIM_Application_ReturnID
, MUIV_Application_ReturnID_Quit
);
1212 DoMethod(ncp
->ncp_UseObj
, MUIM_Notify
, MUIA_Pressed
, FALSE
,
1213 ncp
->ncp_App
, 2, MUIM_Application_ReturnID
, ID_STORE_CONFIG
);
1214 DoMethod(ncp
->ncp_SetDefaultObj
, MUIM_Notify
, MUIA_Pressed
, FALSE
,
1215 ncp
->ncp_App
, 2, MUIM_Application_ReturnID
, ID_DEF_CONFIG
);
1216 DoMethod(ncp
->ncp_CloseObj
, MUIM_Notify
, MUIA_Pressed
, FALSE
,
1217 ncp
->ncp_App
, 2, MUIM_Application_ReturnID
, MUIV_Application_ReturnID_Quit
);
1219 DoMethod(ncp
->ncp_AboutMI
, MUIM_Notify
, MUIA_Menuitem_Trigger
, MUIV_EveryTime
,
1220 ncp
->ncp_App
, 2, MUIM_Application_ReturnID
, ID_ABOUT
);
1221 DoMethod(ncp
->ncp_UseMI
, MUIM_Notify
, MUIA_Menuitem_Trigger
, MUIV_EveryTime
,
1222 ncp
->ncp_App
, 2, MUIM_Application_ReturnID
, ID_STORE_CONFIG
);
1223 DoMethod(ncp
->ncp_SetDefaultMI
, MUIM_Notify
, MUIA_Menuitem_Trigger
, MUIV_EveryTime
,
1224 ncp
->ncp_App
, 2, MUIM_Application_ReturnID
, ID_DEF_CONFIG
);
1225 DoMethod(ncp
->ncp_MUIPrefsMI
, MUIM_Notify
, MUIA_Menuitem_Trigger
, MUIV_EveryTime
,
1226 ncp
->ncp_App
, 2, MUIM_Application_OpenConfigWindow
, 0);
1234 get(ncp
->ncp_App
, MUIA_Application_Iconified
, &iconify
);
1235 set(ncp
->ncp_MainWindow
, MUIA_Window_Open
, TRUE
);
1236 get(ncp
->ncp_MainWindow
, MUIA_Window_Open
, &isopen
);
1237 if(!(isopen
|| iconify
))
1239 nGUITaskCleanup(ncp
);
1245 retid
= DoMethod(ncp
->ncp_App
, MUIM_Application_NewInput
, &sigs
);
1249 case ID_STORE_CONFIG
:
1250 case MUIV_Application_ReturnID_Quit
:
1251 get(ncp
->ncp_UnitObj
, MUIA_String_Integer
, &ncp
->ncp_CDC
->cdc_DefaultUnit
);
1252 get(ncp
->ncp_StackAutoObj
, MUIA_Selected
, &ncp
->ncp_CDC
->cdc_StackAuto
);
1254 if(retid
== ID_DEF_CONFIG
)
1256 pic
= psdGetClsCfg(libname
);
1259 psdSetClsCfg(libname
, NULL
);
1260 pic
= psdGetClsCfg(libname
);
1264 if(psdAddCfgEntry(pic
, ncp
->ncp_CDC
))
1266 psdSaveCfgToDisk(NULL
, FALSE
);
1270 if(ncp
->ncp_Interface
)
1272 pic
= psdGetUsbDevCfg(libname
, ncp
->ncp_DevIDString
, ncp
->ncp_IfIDString
);
1275 psdSetUsbDevCfg(libname
, ncp
->ncp_DevIDString
, ncp
->ncp_IfIDString
, NULL
);
1276 pic
= psdGetUsbDevCfg(libname
, ncp
->ncp_DevIDString
, ncp
->ncp_IfIDString
);
1280 if(psdAddCfgEntry(pic
, ncp
->ncp_CDC
))
1282 if(retid
!= MUIV_Application_ReturnID_Quit
)
1284 psdSaveCfgToDisk(NULL
, FALSE
);
1286 retid
= MUIV_Application_ReturnID_Quit
;
1290 retid
= MUIV_Application_ReturnID_Quit
;
1295 MUI_RequestA(ncp
->ncp_App
, ncp
->ncp_MainWindow
, 0, NULL
, "Blimey!", VERSION_STRING
, NULL
);
1298 if(retid
== MUIV_Application_ReturnID_Quit
)
1304 sigs
= Wait(sigs
| sigmask
| SIGBREAKF_CTRL_C
);
1305 if(sigs
& SIGBREAKF_CTRL_C
)
1311 set(ncp
->ncp_MainWindow
, MUIA_Window_Open
, FALSE
);
1313 nGUITaskCleanup(ncp
);
1319 /* /// "nGUITaskCleanup()" */
1320 void nGUITaskCleanup(struct NepClassBT
*ncp
)
1324 MUI_DisposeObject(ncp
->ncp_App
);
1325 ncp
->ncp_App
= NULL
;
1329 CloseLibrary(MUIMasterBase
);
1330 MUIMasterBase
= NULL
;
1334 CloseLibrary(IntuitionBase
);
1335 IntuitionBase
= NULL
;
1343 ncp
->ncp_GUIBinding
= NULL
;
1344 ncp
->ncp_GUITask
= NULL
;
1345 if(ncp
->ncp_ReadySigTask
)
1347 Signal(ncp
->ncp_ReadySigTask
, 1UL<<ncp
->ncp_ReadySignal
);
1349 --ncp
->ncp_ClsBase
->nh_Library
.lib_OpenCnt
;