Documented GVF_SAVE_VAR alongside other flags, and removed a query/doubt
[AROS.git] / rom / usb / classes / bluetooth / bluetooth.class.c
blob46eded3469b1ecd1ea54da4a97e7446e9e710ccb
1 /*
2 *----------------------------------------------------------------------------
3 * bluetooth class for poseidon
4 *----------------------------------------------------------------------------
5 * By Chris Hodges <chrisly@platon42.de>
6 */
8 #include "debug.h"
10 #include "bluetooth.class.h"
12 /* /// "Lib Stuff" */
13 static const STRPTR libname = MOD_NAME_STRING;
15 static
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),
24 (APTR) -1,
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
38 if(UtilityBase)
40 NewList(&nh->nh_Units);
41 nh->nh_MemPool = CreatePool(MEMF_PUBLIC|MEMF_CLEAR, 32*1024, sizeof(struct BTHCIEventMsg));
42 if(nh->nh_MemPool)
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);
52 if(ncp->ncp_CDC)
54 nh->nh_DevBase->np_ClsBase = nh;
55 Forbid();
56 AddDevice((struct Device *) nh->nh_DevBase);
57 nh->nh_DevBase->np_Library.lib_OpenCnt++;
58 Permit();
59 ret = nh;
61 } else {
62 DeletePool(nh->nh_MemPool);
63 KPRINTF(20, ("failed to create usbbluetooth.device\n"));
66 if(!ret)
68 CloseLibrary(UtilityBase);
70 } else {
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));
81 nLoadClassConfig(nh);
82 return(TRUE);
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",
94 UtilityBase));
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);
102 FreeVec(ncp);
103 ncp = (struct NepClassBT *) nh->nh_Units.lh_Head;
105 if(nh->nh_MemPool)
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"));
113 } else {
114 KPRINTF(5, ("libExpunge: Could not expunge, LIBF_DELEXP set!\n"));
115 return(FALSE);
118 return(TRUE);
121 ADD2INITLIB(libInit, 0)
122 ADD2OPENLIB(libOpen, 0)
123 ADD2EXPUNGELIB(libExpunge, 0)
124 /* \\\ */
127 * ***********************************************************************
128 * * Library functions *
129 * ***********************************************************************
132 /* /// "usbAttemptInterfaceBinding()" */
133 struct NepClassBT * usbAttemptInterfaceBinding(struct NepBTBase *nh, struct PsdInterface *pif)
135 struct Library *ps;
136 IPTR ifclass;
137 IPTR subclass;
138 IPTR proto;
140 KPRINTF(1, ("nepBTAttemptInterfaceBinding(%08lx)\n", pif));
141 if((ps = OpenLibrary("poseidon.library", 4)))
143 psdGetAttrs(PGA_INTERFACE, pif,
144 IFA_Class, &ifclass,
145 IFA_SubClass, &subclass,
146 IFA_Protocol, &proto,
147 TAG_DONE);
148 CloseLibrary(ps);
149 if((ifclass == BLUETOOTH_CLASSCODE) &&
150 (subclass == BLUETOOTH_RF_SUBCLASS) &&
151 (proto == BLUETOOTH_PROTO_PRG))
153 APTR *aclin;
154 APTR *aclout;
155 APTR *eventint;
156 aclin = psdFindEndpoint(pif, NULL,
157 EA_IsIn, TRUE,
158 EA_TransferType, USEAF_BULK,
159 TAG_END);
160 aclout = psdFindEndpoint(pif, NULL,
161 EA_IsIn, FALSE,
162 EA_TransferType, USEAF_BULK,
163 TAG_END);
164 eventint = psdFindEndpoint(pif, NULL,
165 EA_IsIn, TRUE,
166 EA_TransferType, USEAF_INTERRUPT,
167 TAG_END);
168 if(aclin && aclout && eventint)
170 return(usbForceInterfaceBinding(nh, pif));
174 return(NULL);
176 /* \\\ */
178 /* /// "usbForceInterfaceBinding()" */
179 struct NepClassBT * usbForceInterfaceBinding(struct NepBTBase *nh, struct PsdInterface *pif)
181 struct Library *ps;
182 struct NepClassBT *ncp;
183 struct NepClassBT *tmpncp;
184 struct PsdConfig *pc;
185 struct PsdDevice *pd;
186 struct ClsDevCfg *cdc;
187 STRPTR devname;
188 STRPTR ifidstr;
189 STRPTR devidstr;
190 IPTR altifnum;
191 IPTR ifnum;
192 IPTR cfgnum;
193 IPTR prodid;
194 IPTR vendid;
195 ULONG unitno;
196 BOOL unitfound;
197 UBYTE buf[64];
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,
207 IFA_Config, &pc,
208 TAG_DONE);
209 psdGetAttrs(PGA_CONFIG, pc,
210 CA_Device, &pd,
211 CA_ConfigNum, &cfgnum,
212 TAG_END);
213 psdGetAttrs(PGA_DEVICE, pd,
214 DA_ProductID, &prodid,
215 DA_VendorID, &vendid,
216 DA_ProductName, &devname,
217 DA_IDString, &devidstr,
218 TAG_END);
219 Forbid();
220 unitfound = FALSE;
221 unitno = (ULONG) -1;
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;
229 unitfound = TRUE;
230 break;
232 ncp = (struct NepClassBT *) ncp->ncp_Unit.unit_MsgPort.mp_Node.ln_Succ;
234 if(!unitfound)
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)))
240 Permit();
241 CloseLibrary(ps);
242 return(NULL);
244 ncp->ncp_CDC = cdc = AllocVec(sizeof(struct ClsDevCfg), MEMF_PUBLIC|MEMF_CLEAR);
245 if(!cdc)
247 Permit();
248 FreeVec(ncp);
249 CloseLibrary(ps);
250 return(NULL);
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)
283 unitno++;
284 tmpncp = (struct NepClassBT *) nh->nh_Units.lh_Head;
285 } else {
286 tmpncp = (struct NepClassBT *) tmpncp->ncp_Unit.unit_MsgPort.mp_Node.ln_Succ;
290 ncp->ncp_UnitNo = unitno;
291 Permit();
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);
300 if(ncp->ncp_Task)
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,
307 ncp->ncp_UnitNo);
309 CloseLibrary(ps);
310 return(ncp);
313 ncp->ncp_ReadySigTask = NULL;
314 //FreeSignal(ncp->ncp_ReadySignal);
315 /* Get rid of unit structure */
316 /*Forbid();
317 Remove((struct Node *) ncp);
318 FreeVec(ncp->ncp_CDC);
319 FreeVec(ncp);
320 Permit();*/
321 CloseLibrary(ps);
323 return(NULL);
325 /* \\\ */
327 /* /// "usbReleaseInterfaceBinding()" */
328 void usbReleaseInterfaceBinding(struct NepBTBase *nh, struct NepClassBT *ncp)
330 struct Library *ps;
331 STRPTR devname;
333 KPRINTF(1, ("nepBTReleaseInterfaceBinding(%08lx)\n", ncp));
334 if((ps = OpenLibrary("poseidon.library", 4)))
336 Forbid();
337 ncp->ncp_ReadySignal = SIGB_SINGLE;
338 ncp->ncp_ReadySigTask = FindTask(NULL);
339 if(ncp->ncp_Task)
341 Signal(ncp->ncp_Task, SIGBREAKF_CTRL_C);
343 Permit();
344 while(ncp->ncp_Task)
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.",
352 devname);
353 /*psdFreeVec(ncp);*/
354 CloseLibrary(ps);
357 /* \\\ */
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)
366 AROS_LIBFUNC_INIT
368 struct TagItem *ti;
369 LONG count = 0;
371 KPRINTF(1, ("nepBTGetAttrsA(%ld, %08lx, %08lx)\n", type, usbstruct, tags));
372 switch(type)
374 case UGA_CLASS:
375 if((ti = FindTagItem(UCCA_Priority, tags)))
377 *((SIPTR *) ti->ti_Data) = 0;
378 count++;
380 if((ti = FindTagItem(UCCA_Description, tags)))
382 *((STRPTR *) ti->ti_Data) = "Bluetooth HCI via usbbluetooth.device";
383 count++;
385 if((ti = FindTagItem(UCCA_HasClassCfgGUI, tags)))
387 *((IPTR *) ti->ti_Data) = TRUE;
388 count++;
390 if((ti = FindTagItem(UCCA_HasBindingCfgGUI, tags)))
392 *((IPTR *) ti->ti_Data) = TRUE;
393 count++;
395 if((ti = FindTagItem(UCCA_AfterDOSRestart, tags)))
397 *((IPTR *) ti->ti_Data) = FALSE;
398 count++;
400 if((ti = FindTagItem(UCCA_UsingDefaultCfg, tags)))
402 *((IPTR *) ti->ti_Data) = nh->nh_DummyNCP.ncp_UsingDefaultCfg;
403 count++;
405 break;
407 case UGA_BINDING:
408 if((ti = FindTagItem(UCBA_UsingDefaultCfg, tags)))
410 *((IPTR *) ti->ti_Data) = ((struct NepClassBT *) usbstruct)->ncp_UsingDefaultCfg;
411 count++;
413 break;
415 return(count);
416 AROS_LIBFUNC_EXIT
418 /* \\\ */
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)
427 AROS_LIBFUNC_INIT
428 return(0);
429 AROS_LIBFUNC_EXIT
431 /* \\\ */
433 /* /// "usbDoMethodA()" */
434 AROS_LH2(IPTR, usbDoMethodA,
435 AROS_LHA(ULONG, methodid, D0),
436 AROS_LHA(IPTR *, methoddata, A1),
437 LIBBASETYPEPTR, nh, 7, nep)
439 AROS_LIBFUNC_INIT
441 struct NepClassBT *ncp;
443 KPRINTF(10, ("Do Method %ld\n", methodid));
444 switch(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]);
454 return(TRUE);
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);
464 Forbid();
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;
471 Permit();
472 return(TRUE);
474 default:
475 break;
477 return(0);
478 AROS_LIBFUNC_EXIT
480 /* \\\ */
482 /* /// "nLoadClassConfig()" */
483 BOOL nLoadClassConfig(struct NepBTBase *nh)
485 struct NepClassBT *ncp = &nh->nh_DummyNCP;
486 struct Library *ps;
487 struct ClsDevCfg *cdc;
488 struct PsdIFFContext *pic;
490 KPRINTF(10, ("Loading Class Config...\n"));
491 if(ncp->ncp_GUITask)
493 return(FALSE);
495 if(!(ps = OpenLibrary("poseidon.library", 4)))
497 return(FALSE);
500 Forbid();
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);
508 if(pic)
510 cdc = psdGetCfgChunk(pic, AROS_LONG2BE(ncp->ncp_CDC->cdc_ChunkID));
511 if(cdc)
513 CopyMem(((UBYTE *) cdc) + 8, ((UBYTE *) ncp->ncp_CDC) + 8, min(AROS_LONG2BE(cdc->cdc_Length), AROS_LONG2BE(ncp->ncp_CDC->cdc_Length)));
514 psdFreeVec(cdc);
515 ncp->ncp_UsingDefaultCfg = FALSE;
518 Permit();
519 CloseLibrary(ps);
520 return(FALSE);
522 /* \\\ */
524 /* /// "nLoadBindingConfig()" */
525 BOOL nLoadBindingConfig(struct NepClassBT *ncp)
527 struct NepBTBase *nh = ncp->ncp_ClsBase;
528 struct Library *ps;
529 struct ClsDevCfg *cdc;
530 struct PsdIFFContext *pic;
532 KPRINTF(10, ("Loading Binding Config...\n"));
533 if(ncp->ncp_GUITask)
535 return(FALSE);
537 //nLoadClassConfig(nh);
538 *ncp->ncp_CDC = *nh->nh_DummyNCP.ncp_CDC;
539 ncp->ncp_UsingDefaultCfg = TRUE;
541 if(!(ps = OpenLibrary("poseidon.library", 4)))
543 return(FALSE);
546 Forbid();
547 /* Load config */
548 pic = psdGetUsbDevCfg(libname, ncp->ncp_DevIDString, ncp->ncp_IfIDString);
549 if(pic)
551 cdc = psdGetCfgChunk(pic, AROS_LONG2BE(ncp->ncp_CDC->cdc_ChunkID));
552 if(cdc)
554 CopyMem(((UBYTE *) cdc) + 8, ((UBYTE *) ncp->ncp_CDC) + 8, min(AROS_LONG2BE(cdc->cdc_Length), AROS_LONG2BE(ncp->ncp_CDC->cdc_Length)));
555 psdFreeVec(cdc);
556 ncp->ncp_UsingDefaultCfg = FALSE;
559 Permit();
560 CloseLibrary(ps);
561 return(FALSE);
563 /* \\\ */
565 /* /// "nOpenBindingCfgWindow()" */
566 LONG nOpenBindingCfgWindow(struct NepBTBase *nh, struct NepClassBT *ncp)
568 struct Library *ps;
569 KPRINTF(10, ("Opening GUI...\n"));
570 if(!(ps = OpenLibrary("poseidon.library", 4)))
572 return(FALSE);
574 Forbid();
575 if(!ncp->ncp_GUITask)
577 if((ncp->ncp_GUITask = psdSpawnSubTask(MOD_NAME_STRING " GUI", nGUITask, ncp)))
579 Permit();
580 CloseLibrary(ps);
581 return(TRUE);
584 Permit();
585 CloseLibrary(ps);
586 return(FALSE);
588 /* \\\ */
590 /**************************************************************************/
592 #undef ps
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);
600 if(!bem)
602 bem = psdAllocVec(sizeof(struct BTHCIEventMsg));
603 if(!bem)
605 return;
607 bem->bem_Msg.mn_ReplyPort = ncp->ncp_EventReplyPort;
608 } else {
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);
615 /* \\\ */
617 /* /// "nBTTask()" */
618 AROS_UFH0(void, nBTTask)
620 AROS_USERFUNC_INIT
622 struct NepClassBT *ncp;
623 struct PsdPipe *pp;
624 ULONG sigmask;
625 ULONG sigs;
626 LONG ioerr;
627 struct IOBTHCIReq *ioreq;
628 struct IOBTHCIReq *ioreq2;
629 struct BTHCIEventMsg *bem;
630 ULONG len;
632 if((ncp = nAllocBT()))
634 Forbid();
635 if(ncp->ncp_ReadySigTask)
637 Signal(ncp->ncp_ReadySigTask, 1UL<<ncp->ncp_ReadySignal);
639 Permit();
641 /* Main task */
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)
649 nIssueEventReq(ncp);
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);
673 if(ioerr)
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);
698 } else {
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);
711 } else {
712 PutMsg(ncp->ncp_EventReplyPort, &bem->bem_Msg);
714 ncp->ncp_EventsPending++;
715 ncp->ncp_CurrEventMsg = NULL;
716 nIssueEventReq(ncp);
721 else if(pp == ncp->ncp_EPACLOutPipe)
723 if((ioreq = ncp->ncp_WritePending))
725 ioerr = psdGetPipeError(pp);
726 ioreq->iobt_Actual = psdGetPipeActual(pp);
727 if(ioerr)
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);
744 if(ioerr)
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)
763 case BTCMD_READACL:
764 ioreq->iobt_Actual = 0;
765 Forbid();
766 AddTail(&ncp->ncp_ReadQueue, &ioreq->iobt_Req.io_Message.mn_Node);
767 Permit();
768 break;
770 case BTCMD_WRITEACL:
771 ioreq->iobt_Actual = 0;
772 Forbid();
773 AddTail(&ncp->ncp_WriteQueue, &ioreq->iobt_Req.io_Message.mn_Node);
774 Permit();
775 break;
777 case BTCMD_WRITEHCI:
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,
781 0, 0, 0);
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);
787 break;
789 case CMD_RESET:
790 // nop
791 /* Reset does a flush too */
792 case CMD_FLUSH:
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);
826 break;
828 default:
829 ioreq->iobt_Req.io_Error = IOERR_NOCMD;
830 ReplyMsg((struct Message *) ioreq);
831 break;
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));
850 Forbid();
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;
899 /* Command queue */
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);
906 Permit();
907 KPRINTF(20, ("Going down the river!\n"));
908 nFreeBT(ncp);
911 AROS_USERFUNC_EXIT
913 /* \\\ */
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)))
927 Alert(AG_OpenLib);
928 break;
931 ncp->ncp_EPACLIn = psdFindEndpoint(ncp->ncp_Interface, NULL,
932 EA_IsIn, TRUE,
933 EA_TransferType, USEAF_BULK,
934 TAG_END);
935 ncp->ncp_EPACLOut = psdFindEndpoint(ncp->ncp_Interface, NULL,
936 EA_IsIn, FALSE,
937 EA_TransferType, USEAF_BULK,
938 TAG_END);
939 ncp->ncp_EPEventInt = psdFindEndpoint(ncp->ncp_Interface, NULL,
940 EA_IsIn, TRUE,
941 EA_TransferType, USEAF_INTERRUPT,
942 TAG_END);
944 if(!(ncp->ncp_EPACLIn && ncp->ncp_EPACLOut && ncp->ncp_EPEventInt))
946 psdAddErrorMsg(RETURN_FAIL, (STRPTR) libname, "IN or OUT endpoint missing!");
947 break;
950 psdGetAttrs(PGA_ENDPOINT, ncp->ncp_EPACLIn,
951 EA_MaxPktSize, &ncp->ncp_EPACLInMaxPktSize,
952 TAG_END);
954 psdGetAttrs(PGA_ENDPOINT, ncp->ncp_EPEventInt,
955 EA_MaxPktSize, &ncp->ncp_EPEventIntMaxPktSize,
956 TAG_END);
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,
973 TAG_END);
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,
981 TAG_END);
982 if((ncp->ncp_EPACLInPipe = psdAllocPipe(ncp->ncp_Device, ncp->ncp_TaskMsgPort, ncp->ncp_EPACLIn)))
984 /* Setup pipe */
985 psdSetAttrs(PGA_PIPE, ncp->ncp_EPACLInPipe,
986 PPA_NakTimeout, FALSE,
987 PPA_NakTimeoutTime, 5000,
988 PPA_AllowRuntPackets, TRUE,
989 TAG_END);
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,
994 TAG_END);
995 ncp->ncp_Task = thistask;
996 return(ncp);
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);
1009 } while(FALSE);
1010 CloseLibrary(ncp->ncp_Base);
1011 Forbid();
1012 ncp->ncp_Task = NULL;
1013 if(ncp->ncp_ReadySigTask)
1015 Signal(ncp->ncp_ReadySigTask, 1UL<<ncp->ncp_ReadySignal);
1017 return(NULL);
1019 /* \\\ */
1021 /* /// "nFreeBT()" */
1022 void nFreeBT(struct NepClassBT *ncp)
1024 struct IOStdReq *ioreq;
1025 Forbid();
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);
1036 Permit();
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)))
1049 psdFreeVec(bem);
1050 ncp->ncp_EventsPending--;
1053 DeleteMsgPort(ncp->ncp_EventReplyPort);
1054 DeleteMsgPort(ncp->ncp_TaskMsgPort);
1055 CloseLibrary(ncp->ncp_Base);
1056 Forbid();
1057 ncp->ncp_Task = NULL;
1058 if(ncp->ncp_ReadySigTask)
1060 Signal(ncp->ncp_ReadySigTask, 1UL<<ncp->ncp_ReadySignal);
1063 /* \\\ */
1065 /**************************************************************************/
1067 /* /// "nGUITask()" */
1068 AROS_UFH0(void, nGUITask)
1070 AROS_USERFUNC_INIT
1072 struct Task *thistask;
1073 struct NepBTBase *nh;
1074 struct NepClassBT *ncp;
1075 struct PsdIFFContext *pic;
1077 thistask = FindTask(NULL);
1078 #undef ps
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);
1093 return;
1096 if(!(IntuitionBase = OpenLibrary("intuition.library", 39)))
1098 KPRINTF(10, ("Couldn't open intuition.library.\n"));
1099 nGUITaskCleanup(ncp);
1100 return;
1102 if(!(ps = OpenLibrary("poseidon.library", 4)))
1104 KPRINTF(10, ("Couldn't open poseidon.library.\n"));
1105 nGUITaskCleanup(ncp);
1106 return;
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)"?",
1122 End),
1123 End,
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",
1128 End),
1129 Child, (IPTR)(ncp->ncp_SetDefaultMI = MenuitemObject,
1130 MUIA_Menuitem_Title, (IPTR)"Save as Default",
1131 MUIA_Menuitem_Shortcut, (IPTR)"D",
1132 End),
1133 Child, (IPTR)MenuitemObject,
1134 MUIA_Menuitem_Title, (IPTR)NM_BARLABEL,
1135 End,
1136 Child, (IPTR)(ncp->ncp_MUIPrefsMI = MenuitemObject,
1137 MUIA_Menuitem_Title, (IPTR)"MUI Settings",
1138 MUIA_Menuitem_Shortcut, (IPTR)"M",
1139 End),
1140 End,
1141 End,
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,
1156 MUIA_CycleChain, 1,
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,
1162 End),
1163 Child, (IPTR)HSpace(0),
1164 End,
1165 Child, (IPTR)Label((IPTR) "Default " DEVNAME " Unit:"),
1166 Child, (IPTR)(ncp->ncp_UnitObj = StringObject,
1167 StringFrame,
1168 MUIA_CycleChain, 1,
1169 MUIA_String_AdvanceOnCR, TRUE,
1170 MUIA_String_Integer, ncp->ncp_CDC->cdc_DefaultUnit,
1171 MUIA_String_Accept, (IPTR)"0123456789",
1172 End),
1173 End,
1174 //Child, HSpace(0),
1175 End,
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,
1182 MUIA_CycleChain, 1,
1183 MUIA_InputMode, MUIV_InputMode_RelVerify,
1184 MUIA_Text_Contents, (IPTR)"\33c Save ",
1185 End),
1186 Child, (IPTR)(ncp->ncp_SetDefaultObj = TextObject, ButtonFrame,
1187 MUIA_Background, MUII_ButtonBack,
1188 MUIA_CycleChain, 1,
1189 MUIA_InputMode, MUIV_InputMode_RelVerify,
1190 MUIA_Text_Contents, (IPTR)(ncp->ncp_Interface ? "\33c Save as Default " : "\33c Save Defaults "),
1191 End),
1192 Child, (IPTR)(ncp->ncp_CloseObj = TextObject, ButtonFrame,
1193 MUIA_Background, MUII_ButtonBack,
1194 MUIA_CycleChain, 1,
1195 MUIA_InputMode, MUIV_InputMode_RelVerify,
1196 MUIA_Text_Contents, (IPTR)"\33c Use ",
1197 End),
1198 End,
1199 End,
1200 End),
1201 End;
1203 if(!ncp->ncp_App)
1205 KPRINTF(10, ("Couldn't create application\n"));
1206 nGUITaskCleanup(ncp);
1207 return;
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);
1228 IPTR isopen = 0;
1229 IPTR iconify = 0;
1230 ULONG sigs;
1231 ULONG sigmask;
1232 LONG retid;
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);
1240 return;
1242 sigmask = 0;
1245 retid = DoMethod(ncp->ncp_App, MUIM_Application_NewInput, &sigs);
1246 switch(retid)
1248 case ID_DEF_CONFIG:
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);
1257 if(!pic)
1259 psdSetClsCfg(libname, NULL);
1260 pic = psdGetClsCfg(libname);
1262 if(pic)
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);
1273 if(!pic)
1275 psdSetUsbDevCfg(libname, ncp->ncp_DevIDString, ncp->ncp_IfIDString, NULL);
1276 pic = psdGetUsbDevCfg(libname, ncp->ncp_DevIDString, ncp->ncp_IfIDString);
1278 if(pic)
1280 if(psdAddCfgEntry(pic, ncp->ncp_CDC))
1282 if(retid != MUIV_Application_ReturnID_Quit)
1284 psdSaveCfgToDisk(NULL, FALSE);
1286 retid = MUIV_Application_ReturnID_Quit;
1289 } else {
1290 retid = MUIV_Application_ReturnID_Quit;
1292 break;
1294 case ID_ABOUT:
1295 MUI_RequestA(ncp->ncp_App, ncp->ncp_MainWindow, 0, NULL, "Blimey!", VERSION_STRING, NULL);
1296 break;
1298 if(retid == MUIV_Application_ReturnID_Quit)
1300 break;
1302 if(sigs)
1304 sigs = Wait(sigs | sigmask | SIGBREAKF_CTRL_C);
1305 if(sigs & SIGBREAKF_CTRL_C)
1307 break;
1310 } while(TRUE);
1311 set(ncp->ncp_MainWindow, MUIA_Window_Open, FALSE);
1313 nGUITaskCleanup(ncp);
1315 AROS_USERFUNC_EXIT
1317 /* \\\ */
1319 /* /// "nGUITaskCleanup()" */
1320 void nGUITaskCleanup(struct NepClassBT *ncp)
1322 if(ncp->ncp_App)
1324 MUI_DisposeObject(ncp->ncp_App);
1325 ncp->ncp_App = NULL;
1327 if(MUIMasterBase)
1329 CloseLibrary(MUIMasterBase);
1330 MUIMasterBase = NULL;
1332 if(IntuitionBase)
1334 CloseLibrary(IntuitionBase);
1335 IntuitionBase = NULL;
1337 if(ps)
1339 CloseLibrary(ps);
1340 ps = NULL;
1342 Forbid();
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;
1351 /* \\\ */