Documented GVF_SAVE_VAR alongside other flags, and removed a query/doubt
[AROS.git] / rom / usb / classes / ptp / ptp.class.c
blob4c1e55a649f5c491443f548bd1a3181d6912fb64
1 /*
2 *----------------------------------------------------------------------------
3 * ptp class for poseidon
4 *----------------------------------------------------------------------------
5 * By Chris Hodges <chrisly@platon42.de>
6 */
8 #include "debug.h"
10 #include "ptp.class.h"
12 #include "numtostr.h"
14 /* /// "Lib Stuff" */
15 static const STRPTR libname = MOD_NAME_STRING;
17 static int libInit(LIBBASETYPEPTR nh)
19 struct NepPTPBase *ret = NULL;
20 struct NepClassPTP *nch;
22 KPRINTF(10, ("libInit nh: 0x%08lx SysBase: 0x%08lx\n", nh, SysBase));
24 nh->nh_UtilityBase = OpenLibrary("utility.library", 39);
26 #define UtilityBase nh->nh_UtilityBase
28 if(UtilityBase)
30 NewList(&nh->nh_Bindings);
31 nch = &nh->nh_DummyNCH;
32 nch->nch_ClsBase = nh;
33 nch->nch_Interface = NULL;
34 nch->nch_CDC = AllocVec(sizeof(struct ClsDevCfg), MEMF_PUBLIC|MEMF_CLEAR);
35 if(nch->nch_CDC)
37 ret = nh;
39 if(!ret)
41 CloseLibrary(UtilityBase);
43 } else {
44 KPRINTF(1, ("libInit: OpenLibrary(\"utility.library\", 39) failed!\n"));
47 KPRINTF(1, ("libInit: Ok\n"));
48 return(ret ? TRUE : FALSE);
51 static int libOpen(LIBBASETYPEPTR nh)
53 KPRINTF(10, ("libOpen nh: 0x%08lx\n", nh));
54 nLoadClassConfig(nh);
55 return(TRUE);
58 static int libExpunge(LIBBASETYPEPTR nh)
60 struct NepClassPTP *nch;
61 KPRINTF(1, ("libExpunge nh: 0x%08lx\n", nh));
62 CloseLibrary((struct Library *) UtilityBase);
63 nch = &nh->nh_DummyNCH;
64 FreeVec(nch->nch_CDC);
65 return(TRUE);
68 ADD2INITLIB(libInit, 0)
69 ADD2OPENLIB(libOpen, 0)
70 ADD2EXPUNGELIB(libExpunge, 0)
71 /* \\\ */
74 * ***********************************************************************
75 * * Library functions *
76 * ***********************************************************************
79 /* /// "usbAttemptInterfaceBinding()" */
80 struct NepClassPTP * usbAttemptInterfaceBinding(struct NepPTPBase *nh, struct PsdInterface *pif)
82 struct Library *ps;
83 IPTR ifclass;
84 IPTR ifsubclass;
85 IPTR ifproto;
86 IPTR subclass;
87 IPTR proto;
88 IPTR devclass;
89 struct PsdDevice *pd;
90 struct PsdConfig *pc;
91 BOOL checkformtp = FALSE;
92 BOOL isptp = FALSE;
94 KPRINTF(1, ("nepPTPAttemptInterfaceBinding(%08lx)\n", pif));
95 if((ps = OpenLibrary("poseidon.library", 4)))
97 psdGetAttrs(PGA_INTERFACE, pif,
98 IFA_Class, &ifclass,
99 IFA_SubClass, &ifsubclass,
100 IFA_Protocol, &ifproto,
101 IFA_Config, &pc,
102 TAG_DONE);
104 if((ifclass == STILLIMG_CLASSCODE) && (ifsubclass == 0x01) && (ifproto == 0x01))
106 isptp = TRUE;
108 if(nh->nh_DummyNCH.nch_CDC->cdc_EnableMTP)
110 psdGetAttrs(PGA_CONFIG, pc,
111 CA_Device, &pd,
112 TAG_END);
113 psdGetAttrs(PGA_DEVICE, pd,
114 DA_Class, &devclass,
115 DA_SubClass, &subclass,
116 DA_Protocol, &proto,
117 TAG_DONE);
118 if(((devclass == 0xff) && (subclass == 0xff) && (proto == 0xff)) ||
119 ((devclass == 0xff) && (!subclass) && (!proto)) ||
120 ((!devclass) && (!subclass) && (!proto)))
122 checkformtp = ((ifclass == 0xff) || (!ifclass)) &&
123 ((ifsubclass == 0xff) || (!ifsubclass)) &&
124 ((ifproto == 0xff) || (!ifproto));
125 if(checkformtp)
127 checkformtp = psdFindEndpoint(pif, NULL,
128 EA_IsIn, TRUE,
129 EA_TransferType, USEAF_BULK,
130 TAG_END) &&
131 psdFindEndpoint(pif, NULL,
132 EA_IsIn, FALSE,
133 EA_TransferType, USEAF_BULK,
134 TAG_END); /*&&
135 psdFindEndpoint(pif, NULL,
136 EA_IsIn, TRUE,
137 EA_TransferType, USEAF_INTERRUPT,
138 TAG_END);*/
140 if(checkformtp)
142 struct MsgPort *mp;
143 struct PsdPipe *pp;
144 STRPTR idstr;
145 if((mp = CreateMsgPort()))
147 if((pp = psdAllocPipe(pd, mp, NULL)))
149 psdSetAttrs(PGA_PIPE, pp,
150 PPA_NakTimeout, TRUE,
151 PPA_NakTimeoutTime, 500,
152 TAG_END);
153 psdAddErrorMsg(RETURN_OK, (STRPTR) libname, "This might be an MTP device, we will look in detail.");
154 idstr = psdGetStringDescriptor(pp, 0xee);
155 if(idstr)
157 if((idstr[0] == 'M') && (idstr[1] == 'S') && (idstr[2] == 'F') && (idstr[3] == 'T'))
159 psdAddErrorMsg(RETURN_OK, (STRPTR) libname, "Trying to use this MTP device with the PTP driver.");
160 isptp = TRUE;
162 psdFreeVec(idstr);
164 psdFreePipe(pp);
166 DeleteMsgPort(mp);
171 CloseLibrary(ps);
172 if(isptp)
174 return(usbForceInterfaceBinding(nh, pif));
177 return(NULL);
179 /* \\\ */
181 /* /// "usbForceInterfaceBinding()" */
182 struct NepClassPTP * usbForceInterfaceBinding(struct NepPTPBase *nh, struct PsdInterface *pif)
184 struct Library *ps;
185 struct NepClassPTP *nch;
186 struct PsdConfig *pc;
187 struct PsdDevice *pd;
188 STRPTR devname;
189 STRPTR ifidstr;
190 STRPTR devidstr;
191 IPTR ifnum;
192 IPTR devclass;
193 IPTR prodid;
194 IPTR ifproto;
195 UBYTE buf[64];
196 struct Task *tmptask;
198 KPRINTF(1, ("nepPTPForceInterfaceBinding(%08lx)\n", pif));
199 if((ps = OpenLibrary("poseidon.library", 4)))
201 psdGetAttrs(PGA_INTERFACE, pif,
202 IFA_Config, &pc,
203 IFA_IDString, &ifidstr,
204 IFA_InterfaceNum, &ifnum,
205 IFA_Protocol, &ifproto,
206 TAG_DONE);
207 psdGetAttrs(PGA_CONFIG, pc,
208 CA_Device, &pd,
209 TAG_END);
210 psdGetAttrs(PGA_DEVICE, pd,
211 DA_ProductName, &devname,
212 DA_Class, &devclass,
213 DA_ProductID, &prodid,
214 DA_IDString, &devidstr,
215 TAG_END);
216 if((nch = AllocVec(sizeof(struct NepClassPTP), MEMF_PUBLIC|MEMF_CLEAR)))
218 nch->nch_ClsBase = nh;
219 nch->nch_CDC = AllocVec(sizeof(struct ClsDevCfg), MEMF_PUBLIC|MEMF_CLEAR);
220 if(!nch->nch_CDC)
222 FreeVec(nch);
223 CloseLibrary(ps);
224 return(NULL);
226 NewList(&nch->nch_Storages);
227 NewList(&nch->nch_FHs);
228 nch->nch_Device = pd;
229 nch->nch_Interface = pif;
230 nch->nch_DevIDString = devidstr;
231 nch->nch_IfIDString = ifidstr;
232 nch->nch_IfNum = ifnum;
234 nLoadBindingConfig(nch);
236 psdSafeRawDoFmt(buf, 64, "ptp.class<%08lx>", nch);
237 nch->nch_ReadySignal = SIGB_SINGLE;
238 nch->nch_ReadySigTask = FindTask(NULL);
239 SetSignal(0, SIGF_SINGLE);
240 if((tmptask = psdSpawnSubTask(buf, nPTPTask, nch)))
242 psdBorrowLocksWait(tmptask, 1UL<<nch->nch_ReadySignal);
243 if(nch->nch_Task)
245 nch->nch_ReadySigTask = NULL;
246 //FreeSignal(nch->nch_ReadySignal);
247 psdAddErrorMsg(RETURN_OK, (STRPTR) libname,
248 "Hold still for images from for '%s'!",
249 devname);
251 Forbid();
252 AddTail(&nh->nh_Bindings, &nch->nch_Node);
253 Permit();
254 CloseLibrary(ps);
255 return(nch);
258 nch->nch_ReadySigTask = NULL;
259 //FreeSignal(nch->nch_ReadySignal);
260 FreeVec(nch->nch_CDC);
261 FreeVec(nch);
262 CloseLibrary(ps);
263 return(nch);
265 CloseLibrary(ps);
267 return(NULL);
270 /* \\\ */
272 /* /// "usbReleaseInterfaceBinding()" */
273 void usbReleaseInterfaceBinding(struct NepPTPBase *nh, struct NepClassPTP *nch)
275 struct Library *ps;
276 struct PsdConfig *pc;
277 struct PsdDevice *pd;
278 STRPTR devname;
280 KPRINTF(1, ("nepPTPReleaseInterfaceBinding(%08lx)\n", nch));
281 if((ps = OpenLibrary("poseidon.library", 4)))
283 Forbid();
284 nch->nch_ReadySignal = SIGB_SINGLE;
285 nch->nch_ReadySigTask = FindTask(NULL);
286 if(nch->nch_GUITask)
288 Signal(nch->nch_GUITask, SIGBREAKF_CTRL_C);
290 Permit();
291 while(nch->nch_GUITask)
293 Wait(1L<<nch->nch_ReadySignal);
296 Forbid();
297 if(nch->nch_Task)
299 Signal(nch->nch_Task, SIGBREAKF_CTRL_C);
301 Permit();
302 while(nch->nch_Task)
304 Wait(1L<<nch->nch_ReadySignal);
306 //FreeSignal(nch->nch_ReadySignal);
307 psdGetAttrs(PGA_INTERFACE, nch->nch_Interface, IFA_Config, &pc, TAG_END);
308 psdGetAttrs(PGA_CONFIG, pc, CA_Device, &pd, TAG_END);
309 psdGetAttrs(PGA_DEVICE, pd, DA_ProductName, &devname, TAG_END);
310 psdAddErrorMsg(RETURN_OK, (STRPTR) libname,
311 "Still pictures of '%s' became fugitive!",
312 devname);
313 Forbid();
314 Remove(&nch->nch_Node);
315 Permit();
316 FreeVec(nch->nch_CDC);
317 FreeVec(nch);
318 CloseLibrary(ps);
321 /* \\\ */
323 /* /// "usbGetAttrsA()" */
324 AROS_LH3(LONG, usbGetAttrsA,
325 AROS_LHA(ULONG, type, D0),
326 AROS_LHA(APTR, usbstruct, A0),
327 AROS_LHA(struct TagItem *, tags, A1),
328 LIBBASETYPEPTR, nh, 5, nep)
330 AROS_LIBFUNC_INIT
332 struct TagItem *ti;
333 LONG count = 0;
335 KPRINTF(1, ("nepPTPGetAttrsA(%ld, %08lx, %08lx)\n", type, usbstruct, tags));
336 switch(type)
338 case UGA_CLASS:
339 if((ti = FindTagItem(UCCA_Priority, tags)))
341 *((SIPTR *) ti->ti_Data) = -100;
342 count++;
344 if((ti = FindTagItem(UCCA_Description, tags)))
346 *((STRPTR *) ti->ti_Data) = "Support for DigiCams and MTP via PictureTransferProtocol (PTP)";
347 count++;
349 if((ti = FindTagItem(UCCA_HasClassCfgGUI, tags)))
351 *((IPTR *) ti->ti_Data) = TRUE;
352 count++;
354 if((ti = FindTagItem(UCCA_HasBindingCfgGUI, tags)))
356 *((IPTR *) ti->ti_Data) = TRUE;
357 count++;
359 if((ti = FindTagItem(UCCA_AfterDOSRestart, tags)))
361 *((IPTR *) ti->ti_Data) = FALSE;
362 count++;
364 if((ti = FindTagItem(UCCA_UsingDefaultCfg, tags)))
366 *((IPTR *) ti->ti_Data) = nh->nh_DummyNCH.nch_UsingDefaultCfg;
367 count++;
369 break;
371 case UGA_BINDING:
372 if((ti = FindTagItem(UCBA_UsingDefaultCfg, tags)))
374 *((IPTR *) ti->ti_Data) = ((struct NepClassPTP *) usbstruct)->nch_UsingDefaultCfg;
375 count++;
377 break;
379 return(count);
380 AROS_LIBFUNC_EXIT
382 /* \\\ */
384 /* /// "usbSetAttrsA()" */
385 AROS_LH3(LONG, usbSetAttrsA,
386 AROS_LHA(ULONG, type, D0),
387 AROS_LHA(APTR, usbstruct, A0),
388 AROS_LHA(struct TagItem *, tags, A1),
389 LIBBASETYPEPTR, nh, 6, nep)
391 AROS_LIBFUNC_INIT
392 return(0);
393 AROS_LIBFUNC_EXIT
395 /* \\\ */
397 /* /// "usbDoMethodA()" */
398 AROS_LH2(IPTR, usbDoMethodA,
399 AROS_LHA(ULONG, methodid, D0),
400 AROS_LHA(IPTR *, methoddata, A1),
401 LIBBASETYPEPTR, nh, 7, nep)
403 AROS_LIBFUNC_INIT
405 struct NepClassPTP *nch;
407 KPRINTF(1, ("Do Method %ld\n", methodid));
408 switch(methodid)
410 case UCM_AttemptInterfaceBinding:
411 return((IPTR) usbAttemptInterfaceBinding(nh, (struct PsdInterface *) methoddata[0]));
413 case UCM_ForceInterfaceBinding:
414 return((IPTR) usbForceInterfaceBinding(nh, (struct PsdInterface *) methoddata[0]));
416 case UCM_ReleaseInterfaceBinding:
417 usbReleaseInterfaceBinding(nh, (struct NepClassPTP *) methoddata[0]);
418 return(TRUE);
420 case UCM_OpenCfgWindow:
421 return(nOpenBindingCfgWindow(nh, &nh->nh_DummyNCH));
423 case UCM_OpenBindingCfgWindow:
424 return(nOpenBindingCfgWindow(nh, (struct NepClassPTP *) methoddata[0]));
426 case UCM_ConfigChangedEvent:
427 nLoadClassConfig(nh);
428 Forbid();
429 nch = (struct NepClassPTP *) nh->nh_Bindings.lh_Head;
430 while(nch->nch_Node.ln_Succ)
432 nLoadBindingConfig(nch);
433 nch = (struct NepClassPTP *) nch->nch_Node.ln_Succ;
435 Permit();
436 return(TRUE);
438 default:
439 break;
441 return(0);
442 AROS_LIBFUNC_EXIT
444 /* \\\ */
446 /* /// "nLoadClassConfig()" */
447 BOOL nLoadClassConfig(struct NepPTPBase *nh)
449 struct NepClassPTP *nch = &nh->nh_DummyNCH;
450 struct Library *ps;
451 struct ClsDevCfg *cdc;
452 struct PsdIFFContext *pic;
454 KPRINTF(1, ("Loading Class Config...\n"));
455 if(nch->nch_GUITask)
457 return(FALSE);
459 if(!(ps = OpenLibrary("poseidon.library", 4)))
461 return(FALSE);
464 Forbid();
465 /* Create default config */
466 nch->nch_CDC->cdc_ChunkID = AROS_LONG2BE(MAKE_ID('P','T','P','C'));
467 nch->nch_CDC->cdc_Length = AROS_LONG2BE(sizeof(struct ClsDevCfg)-8);
468 nch->nch_CDC->cdc_EnableMTP = FALSE;
469 nch->nch_CDC->cdc_NoPartObj = FALSE;
470 strcpy(nch->nch_CDC->cdc_DOSName, "PTP");
471 nch->nch_UsingDefaultCfg = TRUE;
472 /* try to load default config */
473 pic = psdGetClsCfg(libname);
474 if(pic)
476 cdc = psdGetCfgChunk(pic, AROS_LONG2BE(nch->nch_CDC->cdc_ChunkID));
477 if(cdc)
479 CopyMem(((UBYTE *) cdc) + 8, ((UBYTE *) nch->nch_CDC) + 8, min(AROS_LONG2BE(cdc->cdc_Length), AROS_LONG2BE(nch->nch_CDC->cdc_Length)));
480 psdFreeVec(cdc);
481 nch->nch_UsingDefaultCfg = FALSE;
484 Permit();
485 CloseLibrary(ps);
486 return(FALSE);
488 /* \\\ */
490 /* /// "nLoadBindingConfig()" */
491 BOOL nLoadBindingConfig(struct NepClassPTP *nch)
493 struct NepPTPBase *nh = nch->nch_ClsBase;
494 struct Library *ps;
495 struct ClsDevCfg *cdc;
496 struct PsdIFFContext *pic;
498 KPRINTF(1, ("Loading Binding Config...\n"));
499 if(nch->nch_GUITask)
501 return(FALSE);
503 nLoadClassConfig(nh);
504 *nch->nch_CDC = *nh->nh_DummyNCH.nch_CDC;
505 nch->nch_UsingDefaultCfg = TRUE;
507 if(!(ps = OpenLibrary("poseidon.library", 4)))
509 return(FALSE);
512 Forbid();
513 /* Load config */
514 pic = psdGetUsbDevCfg(libname, nch->nch_DevIDString, nch->nch_IfIDString);
515 if(pic)
517 cdc = psdGetCfgChunk(pic, AROS_LONG2BE(nch->nch_CDC->cdc_ChunkID));
518 if(cdc)
520 CopyMem(((UBYTE *) cdc) + 8, ((UBYTE *) nch->nch_CDC) + 8, min(AROS_LONG2BE(cdc->cdc_Length), AROS_LONG2BE(nch->nch_CDC->cdc_Length)));
521 psdFreeVec(cdc);
522 nch->nch_UsingDefaultCfg = FALSE;
525 Permit();
526 CloseLibrary(ps);
527 return(FALSE);
529 /* \\\ */
531 /* /// "nOpenBindingCfgWindow()" */
532 LONG nOpenBindingCfgWindow(struct NepPTPBase *nh, struct NepClassPTP *nch)
534 struct Library *ps;
535 KPRINTF(1, ("Opening GUI...\n"));
536 if(!(ps = OpenLibrary("poseidon.library", 4)))
538 return(FALSE);
540 Forbid();
541 if(!nch->nch_GUITask)
543 if((nch->nch_GUITask = psdSpawnSubTask(MOD_NAME_STRING " GUI", nGUITask, nch)))
545 Permit();
546 CloseLibrary(ps);
547 return(TRUE);
550 Permit();
551 CloseLibrary(ps);
552 return(FALSE);
554 /* \\\ */
556 /**************************************************************************/
558 #undef ps
559 #define ps nch->nch_Base
560 #undef DOSBase
561 #define DOSBase nch->nch_DOSBase
563 /* /// "BSTR Macros" */
564 #define b2cstr(bstr, cstr) { ULONG i; for (i = 0; i < bstr[0]; i++) cstr[i] = bstr[i + 1]; cstr[i] = 0x00; }
565 #define c2bstr(cstr, bstr)\
568 int i = 0;\
569 UBYTE c;\
570 STRPTR cp = (STRPTR) (cstr);\
571 STRPTR bp = (STRPTR) (bstr);\
572 while((c = cp[i]))\
574 bp[++i] = c;\
576 bp[0] = i;\
577 } while(0)
578 /* \\\ */
580 /* /// "nAllocVec()" */
581 APTR nAllocVec(struct NepClassPTP *nch, ULONG size)
583 ULONG *mem;
584 size += 4;
585 mem = (ULONG *) AllocPooled(nch->nch_MemPool, size);
586 if(!mem)
588 return(NULL);
590 *mem = size;
591 return(mem + 1);
593 /* \\\ */
595 /* /// "nFreeVec()" */
596 void nFreeVec(struct NepClassPTP *nch, APTR mem)
598 ULONG *memptr = (ULONG *) mem;
599 ULONG size;
600 if(!mem)
602 return;
604 size = *(--memptr);
605 if(size < 4)
607 KPRINTF(20, ("illegal size %ld for block %08lx\n", size, memptr));
609 FreePooled(nch->nch_MemPool, memptr, size);
611 /* \\\ */
613 /* /// "nPsdStrToNStr()" */
614 STRPTR nPsdStrToNStr(struct NepClassPTP *nch, STRPTR oldstr)
616 ULONG len = 1;
617 STRPTR strptr = oldstr;
618 STRPTR tarptr;
619 STRPTR newstr;
620 if(!oldstr)
622 return(NULL);
624 while(*strptr++)
626 len++;
628 newstr = nAllocVec(nch, len);
629 if(newstr)
631 strptr = oldstr;
632 tarptr = newstr;
633 while((*tarptr++ = *strptr++));
635 psdFreeVec(oldstr);
636 return(newstr);
638 /* \\\ */
640 /* /// "nSendPTPCmd()" */
641 LONG nSendPTPCmd(struct NepClassPTP *nch, struct PTPOp *po)
643 ULONG len = 4+2+2+4+(po->po_NumParam<<2);
644 LONG ioerr;
645 ULONG cmd = po->po_OpCode;
646 struct PTPOp tmppo;
647 UWORD cnt;
649 KPRINTF(10, ("Sending Command %04lx (%s) with %ld params\n",
650 cmd,
651 nNumToStr(nch, NTS_OPCODE, cmd, "unknown"),
652 po->po_NumParam));
654 tmppo.po_Length = AROS_LONG2LE(len);
655 tmppo.po_ContainerType = AROS_WORD2LE(PCT_COMMAND);
656 tmppo.po_OpCode = AROS_WORD2LE(cmd);
657 //po->po_SessionID = AROS_LONG2LE(nch->nch_SessionID);
658 po->po_TransID = nch->nch_TransID;
659 tmppo.po_TransID = AROS_LONG2LE(nch->nch_TransID);
661 for(cnt = 0; cnt < po->po_NumParam; cnt++)
663 tmppo.po_Param[cnt] = AROS_LONG2LE(po->po_Param[cnt]);
666 if(!(++nch->nch_TransID))
668 nch->nch_TransID++; // 0 not allowed)
671 ioerr = psdDoPipe(nch->nch_EPOutPipe, &tmppo, len);
672 if(ioerr)
674 psdAddErrorMsg(RETURN_ERROR, (STRPTR) libname,
675 "Command '%s' (%04lx) failed: %s (%ld)!",
676 nNumToStr(nch, NTS_OPCODE, cmd, "unknown"), cmd,
677 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
679 return(ioerr);
681 /* \\\ */
683 /* /// "nSendPTPData()" */
684 LONG nSendPTPData(struct NepClassPTP *nch, struct PTPOp *po, UBYTE *data, ULONG datalen)
686 ULONG len = 4+2+2+4+datalen;
687 LONG ioerr;
688 ULONG cmd = po->po_OpCode;
689 struct PTPOp *tmppo = (struct PTPOp *) nch->nch_InBuf;
691 KPRINTF(10, ("Sending Data for Command %04lx (%s) with %ld params\n",
692 cmd,
693 nNumToStr(nch, NTS_OPCODE, cmd, "unknown"),
694 po->po_NumParam));
696 tmppo->po_Length = AROS_LONG2LE(len);
697 tmppo->po_ContainerType = AROS_WORD2LE(PCT_DATA);
698 tmppo->po_OpCode = AROS_WORD2LE(cmd);
699 tmppo->po_TransID = AROS_LONG2LE(po->po_TransID);
700 CopyMem(data, nch->nch_InBuf + 12, 500);
702 psdSetAttrs(PGA_PIPE, nch->nch_EPOutPipe,
703 PPA_NoZeroPktTerm, (datalen < 500) ? FALSE : TRUE,
704 TAG_END);
706 KPRINTF(5, ("Sending data %ld\n", (datalen <= 500) ? len : 512));
707 DB(dumpmem(nch->nch_InBuf, (datalen <= 116) ? len : 128));
709 ioerr = psdDoPipe(nch->nch_EPOutPipe, nch->nch_InBuf, (datalen <= 500) ? len : 512);
710 psdSetAttrs(PGA_PIPE, nch->nch_EPOutPipe,
711 PPA_NoZeroPktTerm, FALSE,
712 TAG_END);
713 if(ioerr)
715 psdAddErrorMsg(RETURN_ERROR, (STRPTR) libname,
716 "Data (1) '%s' (%04lx) failed: %s (%ld)!",
717 nNumToStr(nch, NTS_OPCODE, cmd, "unknown"), cmd,
718 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
719 return(ioerr);
721 if(datalen > 500)
723 ioerr = psdDoPipe(nch->nch_EPOutPipe, &data[500], datalen - 500);
724 if(ioerr)
726 psdAddErrorMsg(RETURN_ERROR, (STRPTR) libname,
727 "Data (2) '%s' (%04lx) failed: %s (%ld)!",
728 nNumToStr(nch, NTS_OPCODE, cmd, "unknown"), cmd,
729 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
732 return(ioerr);
734 /* \\\ */
736 /* /// "nGetPTPRsp()" */
737 UBYTE * nGetPTPRsp(struct NepClassPTP *nch, struct PTPResponse *pr)
739 ULONG len;
740 ULONG iolen;
741 LONG ioerr;
742 UWORD cnt;
743 struct PTPResponse *tmppr = (struct PTPResponse *) nch->nch_InBuf;
744 UBYTE *buf = NULL;
745 UWORD retry = 3;
747 pr->pr_DataLength = 0;
748 pr->pr_RespCode = PRC_UNDEFINED;
750 KPRINTF(1, ("Getting Response\n"));
753 ioerr = psdDoPipe(nch->nch_EPInPipe, nch->nch_InBuf, 512);
754 if(!ioerr)
756 break;
757 } else {
758 KPRINTF(10, ("IOerror %ld, actual=%ld\n", ioerr, psdGetPipeActual(nch->nch_EPInPipe)));
760 } while(--retry);
762 if(ioerr)
764 psdAddErrorMsg(RETURN_ERROR, (STRPTR) libname,
765 "Reading Response failed: %s (%ld)!",
766 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
767 pr->pr_IOErr = ioerr;
768 return(NULL);
771 iolen = psdGetPipeActual(nch->nch_EPInPipe);
772 KPRINTF(5, ("Response received %ld\n", iolen));
773 DB(dumpmem(nch->nch_InBuf, iolen));
774 if(iolen < 12)
776 KPRINTF(20, ("Response %ld too short!\n", iolen));
777 pr->pr_IOErr = UHIOERR_RUNTPACKET;
778 return(NULL);
780 len = AROS_LONG2LE(tmppr->pr_Length);
781 KPRINTF(10, ("Total response %ld\n", len));
782 if(iolen > len)
784 KPRINTF(20, ("Response %ld exceeds %ld length field!\n", iolen , len));
785 pr->pr_IOErr = UHIOERR_RUNTPACKET;
786 return(NULL);
789 if((len < 512) && (iolen < len))
791 KPRINTF(20, ("Response %ld shorter than %ld length field!\n", iolen, len));
793 if(iolen == 12)
795 KPRINTF(1, ("Assuming that data follows in a separate transfer.\n"));
796 } else {
797 pr->pr_IOErr = UHIOERR_RUNTPACKET;
798 return(NULL);
802 pr->pr_IOErr = 0;
803 pr->pr_Length = len;
804 pr->pr_ContainerType = AROS_WORD2LE(tmppr->pr_ContainerType);
805 pr->pr_RespCode = AROS_WORD2LE(tmppr->pr_RespCode);
806 if(pr->pr_TransID != AROS_LONG2LE(tmppr->pr_TransID))
808 KPRINTF(20, ("TransID %08lx != %08lx mismatch!\n", pr->pr_TransID, AROS_LONG2LE(tmppr->pr_TransID)));
811 KPRINTF(1, ("Container type %ld\n", pr->pr_ContainerType));
813 if(pr->pr_ContainerType == PCT_DATA)
815 pr->pr_DataLength = len - 12;
816 KPRINTF(1, ("Data %ld!\n", pr->pr_DataLength));
817 buf = nAllocVec(nch, pr->pr_DataLength);
818 if(!buf)
820 pr->pr_IOErr = UHIOERR_OUTOFMEMORY;
821 return(NULL);
823 CopyMem(&nch->nch_InBuf[12], buf, iolen - 12);
824 if(len > iolen)
826 retry = 3;
829 ioerr = psdDoPipe(nch->nch_EPInPipe, &buf[iolen - 12], len - iolen);
830 if(!ioerr)
832 break;
834 } while(--retry);
836 if(ioerr)
838 psdAddErrorMsg(RETURN_ERROR, (STRPTR) libname,
839 "Reading Data failed: %s (%ld)!",
840 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
841 pr->pr_IOErr = ioerr;
842 nFreeVec(nch, buf);
843 return(NULL);
846 if(!(len % nch->nch_EPInPktSize))
848 KPRINTF(10, ("Reading zero packet\n"));
849 ioerr = psdDoPipe(nch->nch_EPInPipe, NULL, 0);
851 DB(dumpmem(buf, (len < 256+12) ? len - 12 : 256));
852 KPRINTF(1, ("Got Data. Getting Response\n"));
853 retry = 3;
856 ioerr = psdDoPipe(nch->nch_EPInPipe, nch->nch_InBuf, 512);
857 if(!ioerr)
859 break;
861 } while(--retry);
862 if(ioerr)
864 psdAddErrorMsg(RETURN_ERROR, (STRPTR) libname,
865 "Reading Response failed: %s (%ld)!",
866 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
867 pr->pr_IOErr = ioerr;
868 nFreeVec(nch, buf);
869 return(NULL);
872 iolen = psdGetPipeActual(nch->nch_EPInPipe);
873 if(iolen < 12)
875 KPRINTF(20, ("Response %ld too short!\n", iolen));
876 pr->pr_IOErr = UHIOERR_RUNTPACKET;
877 nFreeVec(nch, buf);
878 return(NULL);
880 len = AROS_LONG2LE(tmppr->pr_Length);
881 if(iolen > len)
883 KPRINTF(20, ("Response %ld exceeds %ld length field!\n", iolen , len));
884 pr->pr_IOErr = UHIOERR_RUNTPACKET;
885 nFreeVec(nch, buf);
886 return(NULL);
889 if((len < 512) && (iolen < len))
891 KPRINTF(20, ("Response %ld shorter than %ld length field!\n", iolen, len));
892 pr->pr_IOErr = UHIOERR_RUNTPACKET;
893 nFreeVec(nch, buf);
894 return(NULL);
897 pr->pr_IOErr = 0;
898 pr->pr_Length = len;
899 pr->pr_ContainerType = AROS_WORD2LE(tmppr->pr_ContainerType);
900 pr->pr_RespCode = AROS_WORD2LE(tmppr->pr_RespCode);
901 if(pr->pr_TransID != AROS_LONG2LE(tmppr->pr_TransID))
903 KPRINTF(20, ("TransID %08lx != %08lx mismatch!\n", pr->pr_TransID, AROS_LONG2LE(tmppr->pr_TransID)));
906 KPRINTF(1, ("Container 2 type %ld\n", pr->pr_ContainerType));
909 if(pr->pr_ContainerType == PCT_RESPONSE)
911 pr->pr_NumParam = (len - 12)>>2;
912 KPRINTF(5, ("Response %04lx (%s) with %ld params\n",
913 pr->pr_RespCode,
914 nNumToStr(nch, NTS_RESPCODE, (ULONG) pr->pr_RespCode, "unknown"),
915 pr->pr_NumParam));
916 if(pr->pr_NumParam > 5)
918 pr->pr_NumParam = 5;
919 KPRINTF(10, ("Parameter overflow!\n"));
922 for(cnt = 0; cnt < pr->pr_NumParam; cnt++)
924 pr->pr_Param[cnt] = AROS_LONG2LE(tmppr->pr_Param[cnt]);
925 KPRINTF(1, ("P%ld: %08lx\n", cnt, pr->pr_Param[cnt]));
927 return(buf);
930 return(buf);
932 /* \\\ */
934 /* /// "nGetPTPRspData()" */
935 UBYTE * nGetPTPRspData(struct NepClassPTP *nch, struct PTPResponse *pr, UBYTE *buf, ULONG buflen)
937 ULONG len;
938 ULONG iolen;
939 ULONG remlen;
940 LONG ioerr;
941 UWORD cnt;
942 struct PTPResponse *tmppr = (struct PTPResponse *) nch->nch_InBuf;
943 UWORD retry = 3;
945 pr->pr_DataLength = 0;
946 pr->pr_RespCode = PRC_UNDEFINED;
948 KPRINTF(1, ("Getting Response, buffer %08lx length %ld\n", buf, buflen));
951 ioerr = psdDoPipe(nch->nch_EPInPipe, nch->nch_InBuf, 512);
952 if(!ioerr)
954 break;
955 } else {
956 KPRINTF(10, ("IOerror %ld, actual=%ld\n", ioerr, psdGetPipeActual(nch->nch_EPInPipe)));
958 } while(--retry);
960 if(ioerr)
962 psdAddErrorMsg(RETURN_ERROR, (STRPTR) libname,
963 "Reading Response failed: %s (%ld)!",
964 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
965 pr->pr_IOErr = ioerr;
966 return(NULL);
969 iolen = psdGetPipeActual(nch->nch_EPInPipe);
970 KPRINTF(5, ("Response received %ld\n", iolen));
971 DB(dumpmem(nch->nch_InBuf, iolen));
972 if(iolen < 12)
974 KPRINTF(20, ("Response %ld too short!\n", iolen));
975 pr->pr_IOErr = UHIOERR_RUNTPACKET;
976 return(NULL);
978 len = AROS_LONG2LE(tmppr->pr_Length);
979 KPRINTF(10, ("Total response %ld\n", len));
980 if(iolen > len)
982 KPRINTF(20, ("Response %ld exceeds %ld length field!\n", iolen , len));
983 pr->pr_IOErr = UHIOERR_RUNTPACKET;
984 return(NULL);
987 if((len < 512) && (iolen < len))
989 KPRINTF(20, ("Response %ld shorter than %ld length field!\n", iolen, len));
990 if(iolen == 12)
992 KPRINTF(20, ("Assuming that data follows in a separate transfer.\n"));
993 } else {
994 pr->pr_IOErr = UHIOERR_RUNTPACKET;
995 return(NULL);
999 pr->pr_IOErr = 0;
1000 pr->pr_Length = len;
1001 pr->pr_ContainerType = AROS_WORD2LE(tmppr->pr_ContainerType);
1002 pr->pr_RespCode = AROS_WORD2LE(tmppr->pr_RespCode);
1003 if(pr->pr_TransID != AROS_LONG2LE(tmppr->pr_TransID))
1005 KPRINTF(20, ("TransID %08lx != %08lx mismatch!\n", pr->pr_TransID, AROS_LONG2LE(tmppr->pr_TransID)));
1008 KPRINTF(1, ("Container type %ld\n", pr->pr_ContainerType));
1010 if(pr->pr_ContainerType == PCT_DATA)
1012 pr->pr_DataLength = len - 12;
1013 KPRINTF(5, ("Data %ld!\n", pr->pr_DataLength));
1014 if(pr->pr_DataLength > buflen)
1016 KPRINTF(10, ("Buffer too small to hold complete data\n"));
1018 if(buflen <= iolen - 12)
1020 KPRINTF(10, ("Very small buffer\n"));
1021 CopyMem(&nch->nch_InBuf[12], buf, buflen);
1022 } else {
1023 CopyMem(&nch->nch_InBuf[12], buf, iolen - 12);
1025 if(len > iolen)
1027 if(buflen == len - 12)
1029 retry = 3;
1032 ioerr = psdDoPipe(nch->nch_EPInPipe, &buf[iolen - 12], len - iolen + 12);
1033 if(!ioerr)
1035 break;
1037 } while(--retry);
1038 } else {
1039 remlen = buflen - iolen + 12;
1040 if(remlen & ~511)
1042 ioerr = psdDoPipe(nch->nch_EPInPipe, &buf[iolen - 12], remlen & ~511);
1044 if(!ioerr)
1046 ioerr = psdDoPipe(nch->nch_EPInPipe, nch->nch_InBuf, 512);
1047 if(!ioerr)
1049 CopyMem(nch->nch_EPInPipe, &buf[iolen - 12 + (remlen & ~511)], remlen & 511);
1053 if(ioerr)
1055 psdAddErrorMsg(RETURN_ERROR, (STRPTR) libname,
1056 "Reading Data failed: %s (%ld)!",
1057 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
1058 pr->pr_IOErr = ioerr;
1059 nFreeVec(nch, buf);
1060 return(NULL);
1063 if(!(len % nch->nch_EPInPktSize))
1065 KPRINTF(10, ("Reading zero packet\n"));
1066 ioerr = psdDoPipe(nch->nch_EPInPipe, NULL, 0);
1068 //DB(dumpmem(buf, len - 12));
1069 KPRINTF(5, ("Got Data. Getting Response\n"));
1070 retry = 3;
1073 ioerr = psdDoPipe(nch->nch_EPInPipe, nch->nch_InBuf, 512);
1074 if(!ioerr)
1076 break;
1078 } while(--retry);
1079 if(ioerr)
1081 psdAddErrorMsg(RETURN_ERROR, (STRPTR) libname,
1082 "Reading Response failed: %s (%ld)!",
1083 psdNumToStr(NTS_IOERR, ioerr, "unknown"), ioerr);
1084 pr->pr_IOErr = ioerr;
1085 return(NULL);
1088 iolen = psdGetPipeActual(nch->nch_EPInPipe);
1089 if(iolen < 12)
1091 KPRINTF(20, ("Response %ld too short!\n", iolen));
1092 pr->pr_IOErr = UHIOERR_RUNTPACKET;
1093 return(NULL);
1095 len = AROS_LONG2LE(tmppr->pr_Length);
1096 if(iolen > len)
1098 KPRINTF(20, ("Response %ld exceeds %ld length field!\n", iolen , len));
1099 pr->pr_IOErr = UHIOERR_RUNTPACKET;
1100 return(NULL);
1103 if((len < 512) && (iolen < len))
1105 KPRINTF(20, ("Response %ld shorter than %ld length field!\n", iolen, len));
1106 pr->pr_IOErr = UHIOERR_RUNTPACKET;
1107 return(NULL);
1110 pr->pr_IOErr = 0;
1111 pr->pr_Length = len;
1112 pr->pr_ContainerType = AROS_WORD2LE(tmppr->pr_ContainerType);
1113 pr->pr_RespCode = AROS_WORD2LE(tmppr->pr_RespCode);
1114 if(pr->pr_TransID != AROS_LONG2LE(tmppr->pr_TransID))
1116 KPRINTF(20, ("TransID %08lx != %08lx mismatch!\n", pr->pr_TransID, AROS_LONG2LE(tmppr->pr_TransID)));
1119 KPRINTF(1, ("Container 2 type %ld\n", pr->pr_ContainerType));
1122 if(pr->pr_ContainerType == PCT_RESPONSE)
1124 pr->pr_NumParam = (len - 12)>>2;
1125 KPRINTF(5, ("Response %04lx (%s) with %ld params\n",
1126 pr->pr_RespCode,
1127 nNumToStr(nch, NTS_RESPCODE, (ULONG) pr->pr_RespCode, "unknown"),
1128 pr->pr_NumParam));
1129 if(pr->pr_NumParam > 5)
1131 pr->pr_NumParam = 5;
1132 KPRINTF(10, ("Parameter overflow!\n"));
1135 for(cnt = 0; cnt < pr->pr_NumParam; cnt++)
1137 pr->pr_Param[cnt] = AROS_LONG2LE(tmppr->pr_Param[cnt]);
1138 KPRINTF(1, ("P%ld: %08lx\n", cnt, pr->pr_Param[cnt]));
1140 return(buf);
1143 return(buf);
1145 /* \\\ */
1147 /* /// "nGetPimaStr()" */
1148 STRPTR nGetPimaStr(struct NepClassPTP *nch, UBYTE *bufptr, STRPTR emptystr)
1150 ULONG len = *bufptr++;
1151 STRPTR res;
1152 STRPTR strptr;
1153 UWORD widechar;
1155 if(!len)
1157 if(!emptystr)
1159 return(NULL);
1161 res = nAllocVec(nch, (ULONG) strlen(emptystr) + 1);
1162 if(!res)
1164 return(NULL);
1166 strcpy(res, emptystr);
1167 return(res);
1170 res = nAllocVec(nch, len + 1);
1171 if(!res)
1173 return(NULL);
1176 strptr = res;
1177 while(len)
1179 widechar = *bufptr++;
1180 widechar |= (*bufptr++)<<8;
1181 if(!widechar)
1183 break;
1185 if((widechar > 255) || (widechar < 32))
1187 widechar = '?';
1189 *strptr++ = widechar;
1190 len--;
1192 *strptr = 0;
1193 return(res);
1195 /* \\\ */
1197 /* /// "nGetPimaStrFiltered()" */
1198 STRPTR nGetPimaStrFiltered(struct NepClassPTP *nch, UBYTE *bufptr)
1200 ULONG len = *bufptr++;
1201 STRPTR res = nAllocVec(nch, len + 1);
1202 STRPTR strptr = res;
1203 UWORD widechar;
1205 if(!res)
1207 return(NULL);
1210 while(len)
1212 widechar = *bufptr++;
1213 widechar |= (*bufptr++)<<8;
1214 if(!widechar)
1216 break;
1218 if((widechar > 255) || (widechar < 32))
1220 widechar = '_';
1222 if((widechar == '/') || (widechar == ':') ||
1223 (widechar == '*') || (widechar == '"') ||
1224 (widechar == '\'') || (widechar == '>') ||
1225 (widechar == '<') || (widechar == '\\'))
1227 // ignore
1228 } else {
1229 *strptr++ = widechar;
1231 len--;
1233 *strptr = 0;
1234 return(res);
1236 /* \\\ */
1238 /* /// "nWritePimaStr()" */
1239 UBYTE * nWritePimaStr(struct NepClassPTP *nch, UBYTE *bufptr, STRPTR strptr)
1241 ULONG len;
1242 STRPTR srcptr = strptr;
1244 if(!strptr)
1246 *bufptr++ = 0;
1247 return(bufptr);
1250 len = 1;
1251 while(*srcptr++)
1253 len++;
1256 *bufptr++ = len;
1257 while(*strptr)
1259 *bufptr++ = *strptr++;
1260 *bufptr++ = 0;
1262 *bufptr++ = 0;
1263 *bufptr++ = 0;
1264 return(bufptr);
1266 /* \\\ */
1268 /* /// "nCheckPTPError()" */
1269 BOOL nCheckPTPError(struct NepClassPTP *nch, struct PTPOp *po, struct PTPResponse *pr)
1271 if(pr->pr_IOErr)
1273 psdAddErrorMsg(RETURN_ERROR, (STRPTR) libname,
1274 "Command '%s' (%04lx) response failed: %s (%ld)!",
1275 nNumToStr(nch, NTS_OPCODE, (ULONG) po->po_OpCode, "unknown"), po->po_OpCode,
1276 psdNumToStr(NTS_IOERR, pr->pr_IOErr, "unknown"), pr->pr_IOErr);
1277 return(TRUE);
1280 if(pr->pr_RespCode != PRC_OK)
1282 psdAddErrorMsg(RETURN_ERROR, (STRPTR) libname,
1283 "Command '%s' (%04lx) response failed: '%s' (%04lx).",
1284 nNumToStr(nch, NTS_OPCODE, (ULONG) po->po_OpCode, "unknown"), po->po_OpCode,
1285 nNumToStr(nch, NTS_RESPCODE, (ULONG) pr->pr_RespCode, "unknown"), pr->pr_RespCode);
1286 return(TRUE);
1289 return(FALSE);
1291 /* \\\ */
1293 /* /// "nConvertArrayULONG()" */
1294 BOOL nConvertArrayULONG(struct NepClassPTP *nch, UBYTE *buf, ULONG maxlen)
1296 ULONG cnt;
1297 ULONG *tmpptr = (ULONG *) buf;
1298 ULONG tmpval;
1300 if(maxlen < 4)
1302 KPRINTF(20, ("Array crippled!\n", maxlen));
1303 return(FALSE);
1305 maxlen -= 4;
1306 cnt = *buf++;
1307 cnt |= (*buf++)<<8;
1308 cnt |= (*buf++)<<16;
1309 cnt |= (*buf++)<<24;
1310 if(!cnt)
1312 return(TRUE);
1314 if((cnt<<2) > maxlen)
1316 KPRINTF(20, ("Array exceeds buffer (%ld > %ld)!\n", cnt, maxlen>>2));
1317 cnt = maxlen>>2;
1319 *tmpptr++ = cnt;
1320 if(cnt)
1324 tmpval = *tmpptr;
1325 *tmpptr++ = AROS_LONG2LE(tmpval);
1326 } while(--cnt);
1328 return(TRUE);
1330 /* \\\ */
1332 /* /// "nConvertPimaDate()" */
1333 BOOL nConvertPimaDate(struct NepClassPTP *nch, struct DateStamp *ds, UBYTE *bufptr)
1335 struct NepPTPBase *nh = nch->nch_ClsBase;
1336 struct ClockData cd = { 0, 0, 0, 0, 0, 0, 0 };
1337 ULONG secs;
1338 UWORD ch;
1339 UWORD pos = 0;
1341 ds->ds_Days = 0;
1342 ds->ds_Minute = 0;
1343 ds->ds_Tick = 0;
1345 // 012345678901234
1346 // 20071126T135024
1347 if(*bufptr < 16) // minimum length required
1349 DateStamp(ds);
1350 return(FALSE);
1352 bufptr++;
1353 // parse YYYYMMDDThhmmss
1356 ch = *bufptr++;
1357 ch |= (*bufptr++)<<8;
1358 if((ch < '0') || (ch > '9'))
1360 if(pos == 8)
1362 if(ch != 'T')
1364 return(FALSE);
1366 } else {
1367 return(FALSE);
1370 ch -= '0';
1371 switch(pos)
1373 case 1:
1374 case 2:
1375 case 3:
1376 cd.year *= 10;
1377 case 0:
1378 cd.year += ch;
1379 break;
1381 case 5:
1382 cd.month *= 10;
1383 case 4:
1384 cd.month += ch;
1385 break;
1387 case 7:
1388 cd.mday *= 10;
1389 case 6:
1390 cd.mday += ch;
1391 break;
1393 case 10:
1394 cd.hour *= 10;
1395 case 9:
1396 cd.hour += ch;
1397 break;
1399 case 12:
1400 cd.min *= 10;
1401 case 11:
1402 cd.min += ch;
1403 break;
1405 case 14:
1406 cd.sec *= 10;
1407 case 13:
1408 cd.sec += ch;
1409 break;
1411 } while(++pos < 15);
1413 KPRINTF(1, ("Date: %02ld-%02ld-%04ld %02ld:%02ld:%02ld\n",
1414 cd.mday, cd.month, cd.year, cd.hour, cd.min, cd.sec));
1416 secs = CheckDate(&cd);
1417 if(!secs)
1419 DateStamp(ds);
1420 return(FALSE);
1423 ds->ds_Days = secs / (60*60*24);
1424 ds->ds_Minute = cd.min + cd.hour * 60;
1425 ds->ds_Tick = TICKS_PER_SECOND * cd.sec;
1427 KPRINTF(1, ("Days: %ld, Minute: %ld, Tick: %ld\n", ds->ds_Days, ds->ds_Minute, ds->ds_Tick));
1429 return(TRUE);
1431 /* \\\ */
1433 /* /// "nWritePimaDate()" */
1434 UBYTE * nWritePimaDate(struct NepClassPTP *nch, UBYTE *bufptr, struct DateStamp *ds)
1436 struct NepPTPBase *nh = nch->nch_ClsBase;
1437 struct ClockData cd = { 0, 0, 0, 0, 0, 0, 0 };
1438 ULONG secs;
1439 UBYTE buf[20];
1441 secs = (ds->ds_Tick / TICKS_PER_SECOND) + ds->ds_Minute * 60 + ds->ds_Days * (60*60*24);
1442 Amiga2Date(secs, &cd);
1444 psdSafeRawDoFmt(buf, 20, "%04ld%02ld%02ldT%02ld%02ld%02ld", cd.year, cd.month, cd.mday, cd.hour, cd.min, cd.sec);
1446 bufptr = nWritePimaStr(nch, bufptr, buf);
1448 return(bufptr);
1450 /* \\\ */
1452 /* /// "nCalcNameHash()" */
1453 UWORD nCalcNameHash(struct NepClassPTP *nch, STRPTR ptr)
1455 UWORD hash = 0x1234;
1456 if(!ptr)
1458 return 0;
1460 while(*ptr && (*ptr != '/') && (*ptr != ':'))
1462 hash ^= (hash<<3)|(hash>>13);
1463 hash *= 13;
1464 hash ^= nch->nch_LowCharMap[*ptr++];
1466 return(hash);
1468 /* \\\ */
1470 /* /// "nPTPGetDeviceInfo()" */
1471 BOOL nPTPGetDeviceInfo(struct NepClassPTP *nch)
1473 struct PTPOp po;
1474 struct PTPResponse pr;
1475 UBYTE *buf;
1476 UBYTE *tmpptr;
1477 STRPTR srcptr;
1478 STRPTR tarptr;
1479 ULONG cnt;
1480 ULONG code;
1481 STRPTR manustr;
1482 STRPTR modelstr;
1483 STRPTR devversstr;
1484 STRPTR sernumstr;
1485 STRPTR devname;
1486 STRPTR devmanuname;
1487 LONG ioerr;
1489 po.po_OpCode = POC_GETDEVICEINFO;
1490 po.po_NumParam = 0;
1492 ioerr = nSendPTPCmd(nch, &po);
1493 if(!ioerr)
1495 pr.pr_TransID = po.po_TransID;
1496 tmpptr = buf = nGetPTPRsp(nch, &pr);
1497 if(nCheckPTPError(nch, &po, &pr))
1499 nFreeVec(nch, buf);
1500 return(FALSE);
1502 if(buf)
1504 tmpptr += 2+4+2;
1505 tmpptr += (*tmpptr)<<1; // skip VendorExtensionDesc;
1506 tmpptr += 2;
1507 cnt = *tmpptr++;
1508 cnt |= (*tmpptr++)<<8;
1509 cnt |= (*tmpptr++)<<16;
1510 cnt |= (*tmpptr++)<<24;
1511 KPRINTF(10, ("OpCodes: %ld\n", cnt));
1512 nch->nch_DevCaps = 0;
1513 while(cnt)
1515 code = *tmpptr++;
1516 code |= (*tmpptr++)<<8;
1517 switch(code)
1519 case POC_GETPARTIALOBJECT:
1520 nch->nch_DevCaps |= PTPF_PARTIAL;
1521 if(nch->nch_CDC->cdc_NoPartObj)
1523 psdAddErrorMsg(RETURN_WARN, (STRPTR) libname, "Not fully enabling GetPartialObject even though device supports it (see GUI).");
1525 break;
1527 case POC_SENDOBJECTINFO:
1528 case POC_SENDOBJECT:
1529 nch->nch_DevCaps |= PTPF_SENDOBJ;
1530 break;
1532 case POC_DELETEOBJECT:
1533 nch->nch_DevCaps |= PTPF_DELETEOBJ;
1534 break;
1536 case POC_SETOBJECTPROTECTION:
1537 nch->nch_DevCaps |= PTPF_PROTOBJ;
1538 break;
1540 case POC_MOVEOBJECT:
1541 nch->nch_DevCaps |= PTPF_MOVEOBJ;
1542 break;
1544 case POC_FORMATSTORE:
1545 nch->nch_DevCaps |= PTPF_FORMAT;
1546 break;
1549 KPRINTF(1, ("%04lx: %s\n", code, nNumToStr(nch, NTS_OPCODE, code, "unknown")));
1550 cnt--;
1552 cnt = *tmpptr++;
1553 cnt |= (*tmpptr++)<<8;
1554 cnt |= (*tmpptr++)<<16;
1555 cnt |= (*tmpptr++)<<24;
1556 #if 0
1557 KPRINTF(10, ("EventCodes: %ld\n", cnt));
1558 while(cnt)
1560 code = *tmpptr++;
1561 code |= (*tmpptr++)<<8;
1562 KPRINTF(1, ("%04lx: %s\n", code, nNumToStr(nch, NTS_EVENTCODE, code, "unknown")));
1563 cnt--;
1565 #else
1566 tmpptr += cnt<<1;
1567 #endif
1569 cnt = *tmpptr++;
1570 cnt |= (*tmpptr++)<<8;
1571 cnt |= (*tmpptr++)<<16;
1572 cnt |= (*tmpptr++)<<24;
1573 #if 0
1574 KPRINTF(10, ("DevicePropCodes: %ld\n", cnt));
1575 while(cnt)
1577 code = *tmpptr++;
1578 code |= (*tmpptr++)<<8;
1579 KPRINTF(1, ("%04lx: %s\n", code, nNumToStr(nch, NTS_DEVICEPROPCODE, code, "unknown")));
1580 cnt--;
1582 #else
1583 tmpptr += cnt<<1;
1584 #endif
1586 cnt = *tmpptr++;
1587 cnt |= (*tmpptr++)<<8;
1588 cnt |= (*tmpptr++)<<16;
1589 cnt |= (*tmpptr++)<<24;
1590 #if 0
1591 KPRINTF(10, ("CaptureFormats: %ld\n", cnt));
1592 while(cnt)
1594 code = *tmpptr++;
1595 code |= (*tmpptr++)<<8;
1596 KPRINTF(1, ("%04lx: %s\n", code, nNumToStr(nch, NTS_OBJECTFMTCODE, code, "unknown")));
1597 cnt--;
1599 #else
1600 tmpptr += cnt<<1;
1601 #endif
1603 cnt = *tmpptr++;
1604 cnt |= (*tmpptr++)<<8;
1605 cnt |= (*tmpptr++)<<16;
1606 cnt |= (*tmpptr++)<<24;
1607 #if 0
1608 KPRINTF(10, ("ImageFormats: %ld\n", cnt));
1609 while(cnt)
1611 code = *tmpptr++;
1612 code |= (*tmpptr++)<<8;
1613 KPRINTF(1, ("%04lx: %s\n", code, nNumToStr(nch, NTS_OBJECTFMTCODE, code, "unknown")));
1614 cnt--;
1616 #else
1617 tmpptr += cnt<<1;
1618 #endif
1620 psdGetAttrs(PGA_DEVICE, nch->nch_Device,
1621 DA_ProductName, &devname,
1622 DA_Manufacturer, &devmanuname,
1623 TAG_END);
1625 manustr = nGetPimaStr(nch, tmpptr, devmanuname);
1626 tmpptr += (*tmpptr)<<1; // skip Manufacturer
1627 modelstr = nGetPimaStr(nch, tmpptr, devname);
1628 tmpptr += (*tmpptr)<<1; // skip Model
1629 devversstr = nGetPimaStr(nch, tmpptr, "?.??");
1630 tmpptr += (*tmpptr)<<1; // skip Device Version
1631 sernumstr = nGetPimaStr(nch, tmpptr, "<none>");
1632 tmpptr += (*tmpptr)<<1; // skip Serial Number
1634 // filter model for volume name
1635 cnt = 30;
1636 srcptr = modelstr;
1637 tarptr = nch->nch_VolumeName;
1641 switch(*srcptr)
1643 case ':':
1644 case '/':
1645 case '?':
1646 case '"':
1647 case '\'':
1648 break;
1650 default:
1651 *tarptr++ = *srcptr;
1652 --cnt;
1654 srcptr++;
1655 } while(cnt);
1656 *tarptr = 0;
1658 nch->nch_RootObject.poi_Name = nch->nch_VolumeName;
1659 nch->nch_RootObject.poi_NameHash = nCalcNameHash(nch, nch->nch_VolumeName);
1661 psdAddErrorMsg(RETURN_OK, (STRPTR) libname,
1662 "Model '%s' by '%s'.",
1663 modelstr, manustr);
1664 psdAddErrorMsg(RETURN_OK, (STRPTR) libname,
1665 "Camera Version '%s', Serial '%s'.",
1666 devversstr, sernumstr);
1667 nFreeVec(nch, manustr);
1668 nFreeVec(nch, modelstr);
1669 nFreeVec(nch, devversstr);
1670 nFreeVec(nch, sernumstr);
1672 DB(dumpmem(buf, pr.pr_DataLength));
1673 nFreeVec(nch, buf);
1674 return(TRUE);
1677 return(FALSE);
1679 /* \\\ */
1681 /* /// "nPTPOpenSession()" */
1682 BOOL nPTPOpenSession(struct NepClassPTP *nch)
1684 struct PTPOp po;
1685 struct PTPResponse pr;
1686 LONG ioerr;
1687 UBYTE *buf;
1689 nch->nch_SessionID = 0;
1690 nch->nch_TransID = 0;
1692 po.po_OpCode = POC_OPENSESSION;
1693 po.po_NumParam = 1;
1694 po.po_Param[0] = 1;
1696 ioerr = nSendPTPCmd(nch, &po);
1697 if(!ioerr)
1699 pr.pr_TransID = po.po_TransID;
1700 buf = nGetPTPRsp(nch, &pr);
1701 if(nCheckPTPError(nch, &po, &pr))
1703 nFreeVec(nch, buf);
1704 return(FALSE);
1706 nFreeVec(nch, buf);
1708 nch->nch_SessionID = 1;
1709 return(TRUE);
1711 /* \\\ */
1713 /* /// "nPTPCloseSession()" */
1714 BOOL nPTPCloseSession(struct NepClassPTP *nch)
1716 struct PTPOp po;
1717 struct PTPResponse pr;
1718 LONG ioerr;
1719 UBYTE *buf;
1721 po.po_OpCode = POC_CLOSESESSION;
1722 po.po_NumParam = 0;
1724 ioerr = nSendPTPCmd(nch, &po);
1725 if(!ioerr)
1727 pr.pr_TransID = po.po_TransID;
1728 buf = nGetPTPRsp(nch, &pr);
1729 if(nCheckPTPError(nch, &po, &pr))
1731 nFreeVec(nch, buf);
1732 return(FALSE);
1734 nFreeVec(nch, buf);
1736 nch->nch_SessionID = 0;
1737 return(TRUE);
1739 /* \\\ */
1741 /* /// "nPTPGetObjectHandles()" */
1742 ULONG * nPTPGetObjectHandles(struct NepClassPTP *nch, ULONG storageid, ULONG objhandle)
1744 struct PTPOp po;
1745 struct PTPResponse pr;
1746 LONG ioerr;
1747 UBYTE *buf;
1749 po.po_OpCode = POC_GETOBJECTHANDLES;
1750 po.po_NumParam = 3;
1751 po.po_Param[0] = storageid; // all storageIDs
1752 po.po_Param[1] = 0x00000000; // no special format type
1753 po.po_Param[2] = objhandle; // directory ID
1755 ioerr = nSendPTPCmd(nch, &po);
1756 if(!ioerr)
1758 pr.pr_TransID = po.po_TransID;
1759 buf = nGetPTPRsp(nch, &pr);
1760 if(nCheckPTPError(nch, &po, &pr))
1762 nFreeVec(nch, buf);
1763 return(NULL);
1765 if(nConvertArrayULONG(nch, buf, pr.pr_DataLength))
1767 return((ULONG *) buf);
1769 nFreeVec(nch, buf);
1771 return(NULL);
1773 /* \\\ */
1775 /* /// "nPTPFreeObjectInfo()" */
1776 void nPTPFreeObjectInfo(struct NepClassPTP *nch, struct PTPObjectInfo *poi)
1778 struct PTPObjectInfo *childpoi;
1779 if(!poi)
1781 return;
1783 childpoi = (struct PTPObjectInfo *) poi->poi_Children.mlh_Head;
1784 while(childpoi->poi_Node.mln_Succ)
1786 Remove((struct Node *) childpoi);
1787 nPTPFreeObjectInfo(nch, childpoi);
1788 childpoi = (struct PTPObjectInfo *) poi->poi_Children.mlh_Head;
1790 nFreeVec(nch, poi->poi_Name);
1791 nFreeVec(nch, poi->poi_Keywords);
1792 nFreeVec(nch, poi);
1794 /* \\\ */
1796 /* /// "nPTPCheckObjectInUse()" */
1797 BOOL nPTPCheckObjectInUse(struct NepClassPTP *nch, struct PTPObjectInfo *poi)
1799 struct PTPObjectInfo *childpoi;
1800 BOOL res = FALSE;
1801 if(!poi)
1803 return FALSE;
1805 if(poi->poi_Flags & (PTPF_SHARED_LOCK|PTPF_EXCL_LOCK))
1807 res = TRUE;
1809 childpoi = (struct PTPObjectInfo *) poi->poi_Children.mlh_Head;
1810 while(childpoi->poi_Node.mln_Succ)
1812 res |= nPTPCheckObjectInUse(nch, childpoi);
1813 childpoi = (struct PTPObjectInfo *) childpoi->poi_Node.mln_Succ;
1815 return(res);
1817 /* \\\ */
1819 /* /// "nPTPGetObjectInfo()" */
1820 struct PTPObjectInfo * nPTPGetObjectInfo(struct NepClassPTP *nch, ULONG objhandle)
1822 struct PTPOp po;
1823 struct PTPResponse pr;
1824 LONG ioerr;
1825 UBYTE *buf;
1826 UBYTE *bufptr;
1827 struct PTPObjectInfo *poi;
1828 UWORD protstate;
1830 po.po_OpCode = POC_GETOBJECTINFO;
1831 po.po_NumParam = 1;
1832 po.po_Param[0] = objhandle; // object or directory ID
1834 ioerr = nSendPTPCmd(nch, &po);
1835 if(!ioerr)
1837 pr.pr_TransID = po.po_TransID;
1838 bufptr = buf = nGetPTPRsp(nch, &pr);
1839 if(nCheckPTPError(nch, &po, &pr))
1841 nFreeVec(nch, buf);
1842 return(NULL);
1844 poi = nAllocVec(nch, sizeof(struct PTPObjectInfo));
1845 if(!poi)
1847 nFreeVec(nch, buf);
1848 return(NULL);
1850 NewList((struct List *) &poi->poi_Children);
1851 poi->poi_Handle = objhandle;
1852 poi->poi_StorageID = bufptr[0]|(bufptr[1]<<8)|(bufptr[2]<<16)|(bufptr[3]<<24);
1853 bufptr += 4;
1854 poi->poi_ObjectFmt = bufptr[0]|(bufptr[1]<<8);
1855 bufptr += 2;
1856 protstate = bufptr[0]|(bufptr[1]<<8);
1857 bufptr += 2;
1858 if(protstate == 0x0001)
1860 poi->poi_ProtFlags = FIBF_READ;
1861 } else {
1862 poi->poi_ProtFlags = FIBF_READ|FIBF_WRITE|FIBF_DELETE;
1864 poi->poi_Size = bufptr[0]|(bufptr[1]<<8)|(bufptr[2]<<16)|(bufptr[3]<<24);
1865 bufptr += 4;
1866 poi->poi_ThumbFmt = bufptr[0]|(bufptr[1]<<8);
1867 bufptr += 2;
1868 poi->poi_ThumbSize = bufptr[0]|(bufptr[1]<<8)|(bufptr[2]<<16)|(bufptr[3]<<24);
1869 bufptr += 4;
1870 poi->poi_ThumbWidth = bufptr[0]|(bufptr[1]<<8)|(bufptr[2]<<16)|(bufptr[3]<<24);
1871 bufptr += 4;
1872 poi->poi_ThumbHeight = bufptr[0]|(bufptr[1]<<8)|(bufptr[2]<<16)|(bufptr[3]<<24);
1873 bufptr += 4;
1874 poi->poi_ImageWidth = bufptr[0]|(bufptr[1]<<8)|(bufptr[2]<<16)|(bufptr[3]<<24);
1875 bufptr += 4;
1876 poi->poi_ImageHeight = bufptr[0]|(bufptr[1]<<8)|(bufptr[2]<<16)|(bufptr[3]<<24);
1877 bufptr += 4;
1878 poi->poi_ImageDepth = bufptr[0]|(bufptr[1]<<8)|(bufptr[2]<<16)|(bufptr[3]<<24);
1879 bufptr += 4;
1881 poi->poi_ParentHandle = bufptr[0]|(bufptr[1]<<8)|(bufptr[2]<<16)|(bufptr[3]<<24);
1882 bufptr += 4;
1884 //poi->poi_AssType = bufptr[0]|(bufptr[1]<<8);
1885 bufptr += 2;
1886 //poi->poi_AssDesc = bufptr[0]|(bufptr[1]<<8)|(bufptr[2]<<16)|(bufptr[3]<<24);
1887 bufptr += 4;
1888 //poi->poi_SeqNumber = bufptr[0]|(bufptr[1]<<8)|(bufptr[2]<<16)|(bufptr[3]<<24);
1889 bufptr += 4;
1890 if(*bufptr)
1892 poi->poi_Name = nGetPimaStrFiltered(nch, bufptr);
1893 } else {
1894 poi->poi_Name = nPsdStrToNStr(nch, psdCopyStrFmt("Object_%08lx", poi->poi_StorageID));
1896 bufptr += (*bufptr)<<1; // skip Filename
1897 nConvertPimaDate(nch, &poi->poi_CapDate, bufptr);
1898 bufptr += (*bufptr)<<1; // skip Capture Date
1899 nConvertPimaDate(nch, &poi->poi_ModDate, bufptr);
1900 bufptr += (*bufptr)<<1; // skip Modification Date
1901 if(*bufptr)
1903 poi->poi_Keywords = nGetPimaStr(nch, bufptr, NULL);
1904 } else {
1905 poi->poi_Keywords = NULL;
1907 bufptr += (*bufptr)<<1; // skip Keywords
1909 poi->poi_NameHash = nCalcNameHash(nch, poi->poi_Name);
1911 KPRINTF(5, ("Object %08lx: %s (%04lx), Parent=%08lx, Size %ld, Key=%s\n",
1912 poi->poi_Handle, poi->poi_Name, poi->poi_ObjectFmt, poi->poi_ParentHandle,
1913 poi->poi_Size, poi->poi_Keywords));
1915 KPRINTF(1, ("Thumb (%ld x %ld, %ld bytes), Image (%ld x %ld x %ld bits)\n",
1916 poi->poi_ThumbWidth, poi->poi_ThumbHeight, poi->poi_ThumbSize,
1917 poi->poi_ImageWidth, poi->poi_ImageHeight, poi->poi_ImageDepth));
1919 /*KPRINTF(10, ("Parent %08lx, AssType=%04lx, AssDesc=%08lx\n",
1920 poi->poi_ParentHandle, poi->poi_AssType, poi->poi_AssDesc));*/
1922 return(poi);
1924 return(NULL);
1926 /* \\\ */
1928 /* /// "nPTPSendObject()" */
1929 struct PTPObjectInfo * nPTPSendObject(struct NepClassPTP *nch, struct DosPacket *dp, struct PTPObjectInfo *poi, UBYTE *databuf)
1931 struct PTPOp po;
1932 struct PTPResponse pr;
1933 LONG ioerr;
1934 UBYTE *buf;
1935 UBYTE *bufptr;
1936 UWORD cnt;
1940 po.po_OpCode = POC_SENDOBJECTINFO;
1941 po.po_NumParam = 2;
1942 switch(nch->nch_NoDestMode)
1944 case 0:
1945 po.po_Param[0] = poi->poi_StorageID;
1946 po.po_Param[1] = poi->poi_ParentHandle;
1947 break;
1949 case 1:
1950 po.po_Param[0] = poi->poi_StorageID;
1951 po.po_Param[1] = 0;
1952 break;
1954 case 2:
1955 po.po_Param[0] = 0;
1956 po.po_Param[1] = 0;
1957 break;
1959 ioerr = nSendPTPCmd(nch, &po);
1960 if(ioerr)
1962 dp->dp_Res2 = ERROR_NOT_A_DOS_DISK;
1963 return(NULL);
1965 bufptr = buf = nch->nch_OutBuf;
1966 *bufptr++ = poi->poi_StorageID;
1967 *bufptr++ = poi->poi_StorageID>>8;
1968 *bufptr++ = poi->poi_StorageID>>16;
1969 *bufptr++ = poi->poi_StorageID>>24;
1970 *bufptr++ = poi->poi_ObjectFmt;
1971 *bufptr++ = poi->poi_ObjectFmt>>8;
1972 if(poi->poi_ProtFlags & (FIBF_WRITE|FIBF_DELETE))
1974 *bufptr++ = 0;
1975 *bufptr++ = 0;
1976 } else {
1977 *bufptr++ = 1;
1978 *bufptr++ = 0;
1980 *bufptr++ = poi->poi_Size;
1981 *bufptr++ = poi->poi_Size>>8;
1982 *bufptr++ = poi->poi_Size>>16;
1983 *bufptr++ = poi->poi_Size>>24;
1985 cnt = 2+4+4+4; // thumb
1988 *bufptr++ = 0;
1989 } while(--cnt);
1991 *bufptr++ = poi->poi_ImageWidth;
1992 *bufptr++ = poi->poi_ImageWidth>>8;
1993 *bufptr++ = poi->poi_ImageWidth>>16;
1994 *bufptr++ = poi->poi_ImageWidth>>24;
1995 *bufptr++ = poi->poi_ImageHeight;
1996 *bufptr++ = poi->poi_ImageHeight>>8;
1997 *bufptr++ = poi->poi_ImageHeight>>16;
1998 *bufptr++ = poi->poi_ImageHeight>>24;
1999 *bufptr++ = poi->poi_ImageDepth;
2000 *bufptr++ = poi->poi_ImageDepth>>8;
2001 *bufptr++ = poi->poi_ImageDepth>>16;
2002 *bufptr++ = poi->poi_ImageDepth>>24;
2004 *bufptr++ = poi->poi_ParentHandle;
2005 *bufptr++ = poi->poi_ParentHandle>>8;
2006 *bufptr++ = poi->poi_ParentHandle>>16;
2007 *bufptr++ = poi->poi_ParentHandle>>24;
2009 if(poi->poi_ObjectFmt != POF_ASSOCIATION)
2011 cnt = 2+4+4; // ass typ, desc, seq
2012 } else {
2013 *bufptr++ = 0x01; // generic folder
2014 *bufptr++ = 0x00;
2015 cnt = 4+4;
2019 *bufptr++ = 0;
2020 } while(--cnt);
2022 // filename
2023 bufptr = nWritePimaStr(nch, bufptr, poi->poi_Name);
2024 bufptr = nWritePimaDate(nch, bufptr, &poi->poi_CapDate);
2025 bufptr = nWritePimaDate(nch, bufptr, &poi->poi_ModDate);
2026 bufptr = nWritePimaStr(nch, bufptr, poi->poi_Keywords);
2028 ioerr = nSendPTPData(nch, &po, buf, bufptr - buf);
2029 if(ioerr)
2031 dp->dp_Res2 = ERROR_NOT_A_DOS_DISK;
2032 return(NULL);
2035 pr.pr_TransID = po.po_TransID;
2036 buf = nGetPTPRsp(nch, &pr);
2037 nFreeVec(nch, buf);
2038 if(nCheckPTPError(nch, &po, &pr))
2040 switch(pr.pr_RespCode)
2042 case PRC_STOREREADONLY:
2043 dp->dp_Res2 = ERROR_DISK_WRITE_PROTECTED;
2044 break;
2046 case PRC_ACCESSDENIED:
2047 dp->dp_Res2 = ERROR_WRITE_PROTECTED;
2048 break;
2050 case PRC_STOREFULL:
2051 dp->dp_Res2 = ERROR_DISK_FULL;
2052 break;
2054 case PRC_INVALIDOBJECTFORMATCODE:
2055 dp->dp_Res2 = ERROR_OBJECT_WRONG_TYPE;
2056 break;
2058 case PRC_SPECIFICATIONOFDESTINATIONUNSUPPORTED:
2059 if(nch->nch_NoDestMode < 2)
2061 nch->nch_NoDestMode++;
2062 break;
2065 default:
2066 dp->dp_Res2 = ERROR_NOT_A_DOS_DISK;
2068 if(dp->dp_Res2)
2070 return(NULL);
2072 continue; // retry
2074 break;
2075 } while(TRUE);
2077 poi->poi_StorageID = pr.pr_Param[0];
2078 if(poi->poi_ParentHandle != pr.pr_Param[1])
2080 KPRINTF(20, ("Parent Handle %ld != %ld!\n", poi->poi_ParentHandle, pr.pr_Param[1]));
2081 poi->poi_ParentHandle = pr.pr_Param[1];
2083 poi->poi_Handle = pr.pr_Param[2];
2085 if(!poi->poi_Size)
2087 KPRINTF(5, ("No data stage as size is zero\n"));
2088 return(poi);
2091 po.po_OpCode = POC_SENDOBJECT;
2092 po.po_NumParam = 0;
2094 ioerr = nSendPTPCmd(nch, &po);
2095 if(ioerr)
2097 dp->dp_Res2 = ERROR_NOT_A_DOS_DISK;
2098 return(NULL);
2101 ioerr = nSendPTPData(nch, &po, databuf, poi->poi_Size);
2102 if(ioerr)
2104 dp->dp_Res2 = ERROR_NOT_A_DOS_DISK;
2105 return(NULL);
2107 pr.pr_TransID = po.po_TransID;
2108 buf = nGetPTPRsp(nch, &pr);
2109 nFreeVec(nch, buf);
2110 if(nCheckPTPError(nch, &po, &pr))
2112 switch(pr.pr_RespCode)
2114 case PRC_STOREFULL:
2115 dp->dp_Res2 = ERROR_DISK_FULL;
2116 break;
2118 default:
2119 dp->dp_Res2 = ERROR_NOT_A_DOS_DISK;
2121 return(NULL);
2124 return(poi);
2126 /* \\\ */
2128 /* /// "nPTPGetStorageIDs()" */
2129 ULONG * nPTPGetStorageIDs(struct NepClassPTP *nch)
2131 struct PTPOp po;
2132 struct PTPResponse pr;
2133 LONG ioerr;
2134 UBYTE *buf;
2136 po.po_OpCode = POC_GETSTORAGEIDS;
2137 po.po_NumParam = 0;
2139 ioerr = nSendPTPCmd(nch, &po);
2140 if(!ioerr)
2142 pr.pr_TransID = po.po_TransID;
2143 buf = nGetPTPRsp(nch, &pr);
2144 if(nCheckPTPError(nch, &po, &pr))
2146 nFreeVec(nch, buf);
2147 return(NULL);
2149 if(nConvertArrayULONG(nch, buf, pr.pr_DataLength))
2151 return((ULONG *) buf);
2153 nFreeVec(nch, buf);
2155 return(NULL);
2157 /* \\\ */
2159 /* /// "nPTPFreeStorageInfo()" */
2160 void nPTPFreeStorageInfo(struct NepClassPTP *nch, struct PTPStorageInfo *psi)
2162 if(!psi)
2164 return;
2166 Remove((struct Node *) psi->psi_ObjectInfo);
2167 nPTPFreeObjectInfo(nch, psi->psi_ObjectInfo);
2168 nFreeVec(nch, psi->psi_VolumeName);
2169 nFreeVec(nch, psi->psi_StorageDesc);
2170 nFreeVec(nch, psi);
2172 /* \\\ */
2174 /* /// "nPTPGetStorageInfo()" */
2175 struct PTPStorageInfo * nPTPGetStorageInfo(struct NepClassPTP *nch, ULONG storageid)
2177 struct PTPOp po;
2178 struct PTPResponse pr;
2179 LONG ioerr;
2180 UBYTE *buf;
2181 UBYTE *bufptr;
2182 struct PTPStorageInfo *psi;
2183 struct PTPObjectInfo *poi;
2185 po.po_OpCode = POC_GETSTORAGEINFO;
2186 po.po_NumParam = 1;
2187 po.po_Param[0] = storageid;
2189 ioerr = nSendPTPCmd(nch, &po);
2190 if(!ioerr)
2192 pr.pr_TransID = po.po_TransID;
2193 bufptr = buf = nGetPTPRsp(nch, &pr);
2194 if(nCheckPTPError(nch, &po, &pr))
2196 nFreeVec(nch, buf);
2197 return(NULL);
2199 psi = nAllocVec(nch, sizeof(struct PTPStorageInfo));
2200 if(!psi)
2202 nFreeVec(nch, buf);
2203 return(NULL);
2205 poi = nAllocVec(nch, sizeof(struct PTPObjectInfo));
2206 if(!poi)
2208 nFreeVec(nch, psi);
2209 nFreeVec(nch, buf);
2210 return(NULL);
2212 NewList((struct List *) &poi->poi_Children);
2213 psi->psi_ObjectInfo = poi;
2215 psi->psi_StorageID = storageid;
2216 psi->psi_StorageType = bufptr[0]|(bufptr[1]<<8);
2217 bufptr += 2;
2218 psi->psi_FSType = bufptr[0]|(bufptr[1]<<8);
2219 bufptr += 2;
2220 psi->psi_AccessCaps = bufptr[0]|(bufptr[1]<<8);
2221 bufptr += 2;
2223 psi->psi_MaxCapacityL = bufptr[0]|(bufptr[1]<<8)|(bufptr[2]<<16)|(bufptr[3]<<24);
2224 psi->psi_MaxCapacityH = bufptr[4]|(bufptr[5]<<8)|(bufptr[6]<<16)|(bufptr[7]<<24);
2225 bufptr += 8;
2226 psi->psi_FreeL = bufptr[0]|(bufptr[1]<<8)|(bufptr[2]<<16)|(bufptr[3]<<24);
2227 psi->psi_FreeH = bufptr[4]|(bufptr[5]<<8)|(bufptr[6]<<16)|(bufptr[7]<<24);
2228 bufptr += 8;
2230 psi->psi_FreeImgs = bufptr[0]|(bufptr[1]<<8)|(bufptr[2]<<16)|(bufptr[3]<<24);
2231 bufptr += 4;
2233 if(*bufptr)
2235 psi->psi_StorageDesc = nGetPimaStr(nch, bufptr, NULL);
2236 } else {
2237 psi->psi_StorageDesc = nPsdStrToNStr(nch, psdCopyStrFmt("Storage_%08lx", psi->psi_StorageID));
2239 bufptr += (*bufptr)<<1; // skip Storage Descriptor
2241 if(*bufptr)
2243 psi->psi_VolumeName = nGetPimaStrFiltered(nch, bufptr);
2244 } else {
2245 psi->psi_VolumeName = nPsdStrToNStr(nch, psdCopyStrFmt("Volume_%08lx", psi->psi_StorageID));
2247 bufptr += (*bufptr)<<1; // skip Volume Name
2249 KPRINTF(10, ("StorageID %08lx: %s (%s), StorageType=%04lx, FSType=%04lx, Caps=%04lx\n",
2250 psi->psi_StorageID, psi->psi_VolumeName, psi->psi_StorageDesc,
2251 psi->psi_StorageType, psi->psi_FSType,
2252 psi->psi_AccessCaps));
2254 KPRINTF(10, ("Capacity %lu:%lu, Free %lu:%lu (%lu imgs)\n",
2255 psi->psi_MaxCapacityH, psi->psi_MaxCapacityL,
2256 psi->psi_FreeH, psi->psi_FreeL, psi->psi_FreeImgs));
2258 poi->poi_Handle = 0xffffffff; // as root
2259 poi->poi_StorageID = storageid;
2260 poi->poi_ObjectFmt = POF_ASSOCIATION; // directory
2261 poi->poi_ProtFlags = (psi->psi_AccessCaps == 0x0000) ? FIBF_READ|FIBF_WRITE|FIBF_DELETE : ((psi->psi_AccessCaps == 0x0001) ? FIBF_READ : FIBF_READ|FIBF_DELETE);
2262 nch->nch_RootObject.poi_ProtFlags |= poi->poi_ProtFlags;
2263 poi->poi_ParentHandle = 0; // no parent
2264 poi->poi_Name = nPsdStrToNStr(nch, psdCopyStr(psi->psi_VolumeName));
2265 DateStamp(&poi->poi_CapDate);
2266 DateStamp(&poi->poi_ModDate);
2267 poi->poi_Keywords = NULL;
2268 poi->poi_Parent = &nch->nch_RootObject;
2269 poi->poi_Flags = PTPF_NOPURGE;
2270 poi->poi_NameHash = nCalcNameHash(nch, poi->poi_Name);
2272 AddTail((struct List *) &nch->nch_RootObject.poi_Children, (struct Node *) poi);
2274 return(psi);
2276 return(NULL);
2278 /* \\\ */
2280 /* /// "nPTPRead()" */
2281 void nPTPRead(struct NepClassPTP *nch, struct DosPacket *dp, struct PTPFileHandle *pfh, UBYTE *buffer, ULONG len)
2283 struct PTPObjectInfo *poi = pfh->pfh_ObjectInfo;
2284 struct PTPOp po;
2285 struct PTPResponse pr;
2286 LONG ioerr;
2287 KPRINTF(10, ("Reading %ld at %ld (%08lx, '%s')\n", len, pfh->pfh_SeekPos, poi->poi_Handle, poi->poi_Name));
2289 if(!len)
2291 KPRINTF(10, ("No data to read!\n"));
2292 dp->dp_Res1 = 0;
2293 dp->dp_Res2 = RETURN_OK;
2294 return;
2297 if(pfh->pfh_SeekPos > poi->poi_Size)
2299 KPRINTF(10, ("seek pos %ld past size %ld!\n", pfh->pfh_SeekPos, poi->poi_Size));
2300 dp->dp_Res1 = 0;
2301 dp->dp_Res2 = ERROR_SEEK_ERROR;
2302 return;
2305 if(pfh->pfh_SeekPos + len > poi->poi_Size)
2307 len = poi->poi_Size - pfh->pfh_SeekPos;
2308 KPRINTF(10, ("Reading past end, new length %ld!\n", len));
2309 if(!len)
2311 dp->dp_Res1 = 0;
2312 dp->dp_Res2 = RETURN_OK;
2313 return;
2316 dp->dp_Res1 = len;
2318 if(pfh->pfh_Buffer)
2320 CopyMem(&pfh->pfh_Buffer[pfh->pfh_SeekPos], buffer, len);
2321 pfh->pfh_SeekPos += len;
2322 return;
2325 if((nch->nch_DevCaps & PTPF_PARTIAL) && (!(nch->nch_CDC->cdc_NoPartObj && (len > 32768))))
2327 if(pfh->pfh_SeekPos || (len != poi->poi_Size))
2329 KPRINTF(10, ("Using GetPartialObject\n"));
2330 po.po_OpCode = POC_GETPARTIALOBJECT;
2331 po.po_NumParam = 3;
2332 po.po_Param[0] = poi->poi_Handle;
2333 po.po_Param[1] = pfh->pfh_SeekPos;
2334 po.po_Param[2] = len;
2335 } else {
2336 KPRINTF(10, ("Using GetObject\n"));
2337 po.po_OpCode = POC_GETOBJECT;
2338 po.po_NumParam = 1;
2339 po.po_Param[0] = poi->poi_Handle;
2341 ioerr = nSendPTPCmd(nch, &po);
2342 if(!ioerr)
2344 pr.pr_TransID = po.po_TransID;
2345 nGetPTPRspData(nch, &pr, buffer, len);
2346 if(nCheckPTPError(nch, &po, &pr))
2348 dp->dp_Res1 = 0;
2349 dp->dp_Res2 = ERROR_NOT_A_DOS_DISK;
2350 return;
2352 pfh->pfh_SeekPos += len;
2353 } else {
2354 dp->dp_Res1 = 0;
2355 dp->dp_Res2 = ERROR_NOT_A_DOS_DISK;
2356 return;
2358 } else {
2359 if(!pfh->pfh_Buffer)
2361 if(nch->nch_LastObject == poi)
2363 KPRINTF(10, ("Using Last Object Cache\n"));
2364 pfh->pfh_Buffer = nch->nch_LastBuffer;
2365 pfh->pfh_BufferLen = nch->nch_LastBufferLen;
2366 pfh->pfh_Flags |= PTPF_OLDLOADED;
2367 nch->nch_LastBuffer = NULL;
2368 nch->nch_LastObject = NULL; // make sure we don't try to reuse this value!
2369 } else {
2370 KPRINTF(10, ("Using GetObject\n"));
2371 po.po_OpCode = POC_GETOBJECT;
2372 po.po_NumParam = 1;
2373 po.po_Param[0] = poi->poi_Handle;
2374 ioerr = nSendPTPCmd(nch, &po);
2375 if(!ioerr)
2377 pr.pr_TransID = po.po_TransID;
2378 pfh->pfh_Buffer = nGetPTPRsp(nch, &pr);
2379 pfh->pfh_BufferLen = pr.pr_DataLength;
2380 if(nCheckPTPError(nch, &po, &pr))
2382 nFreeVec(nch, pfh->pfh_Buffer);
2383 pfh->pfh_Buffer = NULL;
2384 dp->dp_Res1 = 0;
2385 dp->dp_Res2 = ERROR_NOT_A_DOS_DISK;
2386 return;
2388 pfh->pfh_Flags |= PTPF_OLDLOADED;
2389 } else {
2390 dp->dp_Res1 = 0;
2391 dp->dp_Res2 = ERROR_NOT_A_DOS_DISK;
2392 return;
2396 CopyMem(&pfh->pfh_Buffer[pfh->pfh_SeekPos], buffer, len);
2397 pfh->pfh_SeekPos += len;
2400 /* \\\ */
2402 /* /// "nPTPWrite()" */
2403 void nPTPWrite(struct NepClassPTP *nch, struct DosPacket *dp, struct PTPFileHandle *pfh, UBYTE *buffer, ULONG len)
2405 struct PTPObjectInfo *poi = pfh->pfh_ObjectInfo;
2406 struct PTPOp po;
2407 struct PTPResponse pr;
2408 LONG ioerr;
2409 UBYTE *newbuffer;
2410 ULONG newbuflen;
2411 KPRINTF(10, ("Write %ld at %ld (%08lx, '%s')\n", len, pfh->pfh_SeekPos, poi->poi_Handle, poi->poi_Name));
2413 if(!len)
2415 KPRINTF(10, ("No data to write\n"));
2416 return;
2419 if(pfh->pfh_SeekPos > poi->poi_Size)
2421 KPRINTF(10, ("seek pos %ld past size %ld!\n", pfh->pfh_SeekPos, poi->poi_Size));
2422 dp->dp_Res1 = 0;
2423 dp->dp_Res2 = ERROR_SEEK_ERROR;
2424 return;
2427 if(!pfh->pfh_Buffer)
2429 pfh->pfh_BufferLen = 0; // make sure that we clear this value to avoid confusion
2432 if(pfh->pfh_SeekPos + len > poi->poi_Size)
2434 KPRINTF(10, ("Writing past end, new length %ld!\n", pfh->pfh_SeekPos + len));
2435 if(pfh->pfh_SeekPos + len > pfh->pfh_BufferLen)
2437 newbuflen = pfh->pfh_BufferLen;
2438 if(newbuflen < poi->poi_Size)
2440 newbuflen = poi->poi_Size; // make sure the buffer is at least the size of the file, when freshly allocating
2442 while(newbuflen < pfh->pfh_SeekPos + len)
2444 if(newbuflen <= (512<<10))
2446 if(newbuflen >= 65536)
2448 newbuflen <<= 1; // double size of buffer
2449 } else {
2450 newbuflen = 65536;
2452 } else {
2453 newbuflen += 512<<10; // increase buffer by 512 KB;
2456 KPRINTF(10, ("New Buffer length: %ld\n", newbuflen));
2457 newbuffer = nAllocVec(nch, newbuflen);
2458 if(!newbuffer)
2460 dp->dp_Res1 = 0;
2461 dp->dp_Res2 = ERROR_NO_FREE_STORE;
2462 return;
2464 if(pfh->pfh_Buffer)
2466 // copy old material and free old buffer
2467 CopyMem(pfh->pfh_Buffer, newbuffer, poi->poi_Size);
2468 nFreeVec(nch, pfh->pfh_Buffer);
2470 pfh->pfh_Buffer = newbuffer;
2471 pfh->pfh_BufferLen = newbuflen;
2474 dp->dp_Res1 = len;
2476 if(!(pfh->pfh_Flags & (PTPF_NEWFILE|PTPF_OLDLOADED)))
2478 if(pfh->pfh_SeekPos || (len < poi->poi_Size))
2480 KPRINTF(10, ("Loading old file using GetObject first\n"));
2481 po.po_OpCode = POC_GETOBJECT;
2482 po.po_NumParam = 1;
2483 po.po_Param[0] = poi->poi_Handle;
2484 ioerr = nSendPTPCmd(nch, &po);
2485 if(!ioerr)
2487 pr.pr_TransID = po.po_TransID;
2488 nGetPTPRspData(nch, &pr, pfh->pfh_Buffer, poi->poi_Size);
2489 if(nCheckPTPError(nch, &po, &pr))
2491 dp->dp_Res1 = 0;
2492 dp->dp_Res2 = ERROR_NOT_A_DOS_DISK;
2493 return;
2495 pfh->pfh_Flags |= PTPF_OLDLOADED;
2496 } else {
2497 dp->dp_Res1 = 0;
2498 dp->dp_Res2 = ERROR_NOT_A_DOS_DISK;
2499 return;
2501 } else {
2502 KPRINTF(10, ("No need to load old file, overwriting all old data\n"));
2503 pfh->pfh_Flags |= PTPF_OLDLOADED;
2507 CopyMem(buffer, &pfh->pfh_Buffer[pfh->pfh_SeekPos], len);
2508 pfh->pfh_SeekPos += len;
2509 if(pfh->pfh_SeekPos > poi->poi_Size)
2511 poi->poi_Size = pfh->pfh_SeekPos;
2513 pfh->pfh_Flags |= PTPF_MODIFIED;
2515 /* \\\ */
2517 /* /// "nPTPSetObjectProtection()" */
2518 void nPTPSetObjectProtection(struct NepClassPTP *nch, struct DosPacket *dp, struct PTPObjectInfo *poi, ULONG protflags)
2520 struct PTPOp po;
2521 struct PTPResponse pr;
2522 UBYTE *buf;
2523 LONG ioerr;
2524 KPRINTF(10, ("SetObjectProtection %04lx on (%08lx, '%s')\n", protflags, poi->poi_Handle, poi->poi_Name));
2526 if((protflags & (FIBF_WRITE|FIBF_DELETE)) != (poi->poi_ProtFlags & (FIBF_WRITE|FIBF_DELETE)))
2528 po.po_OpCode = POC_SETOBJECTPROTECTION;
2529 po.po_NumParam = 2;
2530 po.po_Param[0] = poi->poi_Handle;
2531 if(protflags & (FIBF_WRITE|FIBF_DELETE))
2533 po.po_Param[1] = 0x0000;
2534 protflags |= FIBF_WRITE|FIBF_DELETE;
2535 } else {
2536 po.po_Param[1] = 0x0001;
2537 protflags &= ~(FIBF_WRITE|FIBF_DELETE);
2540 ioerr = nSendPTPCmd(nch, &po);
2541 if(!ioerr)
2543 pr.pr_TransID = po.po_TransID;
2544 buf = nGetPTPRsp(nch, &pr);
2545 if(nCheckPTPError(nch, &po, &pr))
2547 nFreeVec(nch, buf);
2548 switch(pr.pr_RespCode)
2550 case PRC_STOREREADONLY:
2551 dp->dp_Res2 = ERROR_DISK_WRITE_PROTECTED;
2552 break;
2554 case PRC_ACCESSDENIED:
2555 dp->dp_Res2 = ERROR_WRITE_PROTECTED;
2556 break;
2558 default:
2559 dp->dp_Res2 = ERROR_NOT_A_DOS_DISK;
2561 return;
2563 nFreeVec(nch, buf);
2564 } else {
2565 dp->dp_Res2 = ERROR_NOT_A_DOS_DISK;
2566 return;
2569 poi->poi_ProtFlags = protflags;
2571 /* \\\ */
2573 /* /// "nPTPFormatStore()" */
2574 void nPTPFormatStore(struct NepClassPTP *nch, struct DosPacket *dp)
2576 struct PTPOp po;
2577 struct PTPResponse pr;
2578 UBYTE *buf;
2579 LONG ioerr;
2580 struct PTPStorageInfo *psi;
2581 struct PTPStorageInfo *nextpsi;
2582 struct List newinfos;
2584 KPRINTF(10, ("FormatStore\n"));
2586 NewList(&newinfos);
2588 psi = (struct PTPStorageInfo *) nch->nch_Storages.lh_Head;
2589 while((nextpsi = (struct PTPStorageInfo *) psi->psi_Node.ln_Succ))
2591 if(psi->psi_AccessCaps == 0x0000)
2593 if(nPTPCheckObjectInUse(nch, psi->psi_ObjectInfo))
2595 dp->dp_Res2 = ERROR_OBJECT_IN_USE;
2596 } else {
2597 po.po_OpCode = POC_FORMATSTORE;
2598 po.po_NumParam = 2;
2599 po.po_Param[0] = psi->psi_StorageID;
2600 po.po_Param[1] = 0;
2602 ioerr = nSendPTPCmd(nch, &po);
2603 if(!ioerr)
2605 pr.pr_TransID = po.po_TransID;
2606 buf = nGetPTPRsp(nch, &pr);
2607 if(nCheckPTPError(nch, &po, &pr))
2609 switch(pr.pr_RespCode)
2611 case PRC_STOREREADONLY:
2612 dp->dp_Res2 = ERROR_DISK_WRITE_PROTECTED;
2613 return;
2615 case PRC_ACCESSDENIED:
2616 dp->dp_Res2 = ERROR_WRITE_PROTECTED;
2617 return;
2619 default:
2620 dp->dp_Res2 = ERROR_NOT_A_DOS_DISK;
2621 return;
2624 nFreeVec(nch, buf);
2625 dp->dp_Res2 = 0;
2626 Remove(&psi->psi_Node);
2627 nPTPFreeStorageInfo(nch, psi);
2628 psi = nPTPGetStorageInfo(nch, po.po_Param[0]);
2629 if(psi)
2631 AddTail(&newinfos, &psi->psi_Node);
2633 } else {
2634 dp->dp_Res2 = ERROR_NOT_A_DOS_DISK;
2635 return;
2639 psi = nextpsi;
2642 psi = (struct PTPStorageInfo *) newinfos.lh_Head;
2643 while((nextpsi = (struct PTPStorageInfo *) psi->psi_Node.ln_Succ))
2645 Remove(&psi->psi_Node);
2646 AddTail(&nch->nch_Storages, &psi->psi_Node);
2647 psi = nextpsi;
2650 /* \\\ */
2652 /* /// "nPTPMoveObject()" */
2653 void nPTPMoveObject(struct NepClassPTP *nch, struct DosPacket *dp, struct PTPObjectInfo *poi, struct PTPObjectInfo *targetdir)
2655 struct PTPOp po;
2656 struct PTPResponse pr;
2657 UBYTE *buf;
2658 LONG ioerr;
2659 KPRINTF(10, ("MoveObject %08lx, '%s' to %08lx, '%s'\n", poi->poi_Handle, poi->poi_Name, targetdir->poi_Handle, targetdir->poi_Name));
2661 po.po_OpCode = POC_MOVEOBJECT;
2662 po.po_NumParam = 3;
2663 po.po_Param[0] = poi->poi_Handle;
2664 po.po_Param[1] = targetdir->poi_StorageID;
2665 po.po_Param[2] = targetdir->poi_Handle;
2666 ioerr = nSendPTPCmd(nch, &po);
2667 if(!ioerr)
2669 pr.pr_TransID = po.po_TransID;
2670 buf = nGetPTPRsp(nch, &pr);
2671 if(nCheckPTPError(nch, &po, &pr))
2673 nFreeVec(nch, buf);
2674 switch(pr.pr_RespCode)
2676 case PRC_STOREREADONLY:
2677 dp->dp_Res2 = ERROR_DISK_WRITE_PROTECTED;
2678 break;
2680 case PRC_ACCESSDENIED:
2681 dp->dp_Res2 = ERROR_WRITE_PROTECTED;
2682 break;
2684 default:
2685 dp->dp_Res2 = ERROR_NOT_A_DOS_DISK;
2687 return;
2689 nFreeVec(nch, buf);
2690 Remove((struct Node *) poi);
2691 AddTail((struct List *) &targetdir->poi_Children, (struct Node *) poi);
2692 } else {
2693 dp->dp_Res2 = ERROR_NOT_A_DOS_DISK;
2694 return;
2697 /* \\\ */
2699 /* /// "nPTPDeleteObject()" */
2700 void nPTPDeleteObject(struct NepClassPTP *nch, struct DosPacket *dp, struct PTPObjectInfo *poi)
2702 struct PTPOp po;
2703 struct PTPResponse pr;
2704 UBYTE *buf;
2705 LONG ioerr;
2706 KPRINTF(10, ("DeleteObject %08lx, '%s'\n", poi->poi_Handle, poi->poi_Name));
2708 po.po_OpCode = POC_DELETEOBJECT;
2709 po.po_NumParam = 2;
2710 po.po_Param[0] = poi->poi_Handle;
2711 po.po_Param[1] = 0;
2712 ioerr = nSendPTPCmd(nch, &po);
2713 if(!ioerr)
2715 pr.pr_TransID = po.po_TransID;
2716 buf = nGetPTPRsp(nch, &pr);
2717 if(nCheckPTPError(nch, &po, &pr))
2719 nFreeVec(nch, buf);
2720 switch(pr.pr_RespCode)
2722 case PRC_STOREREADONLY:
2723 dp->dp_Res2 = ERROR_DISK_WRITE_PROTECTED;
2724 break;
2726 case PRC_ACCESSDENIED:
2727 case PRC_OBJECTWRITEPROTECTED:
2728 dp->dp_Res2 = ERROR_WRITE_PROTECTED;
2729 break;
2731 default:
2732 dp->dp_Res2 = ERROR_NOT_A_DOS_DISK;
2734 return;
2736 nFreeVec(nch, buf);
2737 } else {
2738 dp->dp_Res2 = ERROR_NOT_A_DOS_DISK;
2739 return;
2742 /* \\\ */
2744 /* /// "nGetObjFromLock()" */
2745 struct PTPObjectInfo * nGetObjFromLock(struct NepClassPTP *nch, BPTR lock)
2747 struct FileLock *fl = (struct FileLock *) BADDR(lock);
2749 if(!lock)
2751 KPRINTF(10, ("Lock NULL\n"));
2752 return(&nch->nch_RootObject);
2754 KPRINTF(1, ("FL=%08lx, ObjectInfo=%08lx\n", fl, fl->fl_Key));
2755 return((struct PTPObjectInfo *) fl->fl_Key);
2757 /* \\\ */
2759 /* /// "nLoadDirectory()" */
2760 BOOL nLoadDirectory(struct NepClassPTP *nch, struct PTPObjectInfo *poi)
2762 ULONG *idarray = nPTPGetObjectHandles(nch, poi->poi_StorageID, poi->poi_Handle);
2763 ULONG cnt;
2764 ULONG handle;
2765 struct PTPObjectInfo *childpoi;
2767 KPRINTF(10, ("Loading directory for %s\n", poi->poi_Name));
2768 if(idarray)
2770 cnt = *idarray;
2771 KPRINTF(10, ("%ld ObjectHandles:\n", cnt));
2772 while(cnt)
2774 handle = idarray[*idarray - cnt + 1];
2775 KPRINTF(1, ("%ld: ObjectHandle %08lx\n", *idarray - cnt, handle));
2776 childpoi = nPTPGetObjectInfo(nch, handle);
2777 if(childpoi)
2779 childpoi->poi_Parent = poi;
2780 AddTail((struct List *) &poi->poi_Children, (struct Node *) childpoi);
2782 cnt--;
2784 nFreeVec(nch, idarray);
2785 poi->poi_Flags |= PTPF_FETCHED;
2786 return(TRUE);
2788 return(FALSE);
2790 /* \\\ */
2792 /* /// "nSearchObject()" */
2793 struct PTPObjectInfo * nSearchObject(struct NepClassPTP *nch, struct DosPacket *dp, struct PTPObjectInfo *dirpoi, STRPTR path)
2795 UWORD namehash;
2796 STRPTR srcptr;
2797 struct PTPObjectInfo *childpoi;
2799 if(!(*path))
2801 KPRINTF(10, ("Empty path!\n"));
2802 return(dirpoi);
2805 KPRINTF(10, ("Searching path %s from %s on\n", path, dirpoi->poi_Name));
2806 // search for ':'
2807 srcptr = path;
2808 while(*srcptr && (*srcptr != '/'))
2810 if(*srcptr == ':')
2812 KPRINTF(5, ("Rooting!\n"));
2813 dirpoi = &nch->nch_RootObject;
2814 path = ++srcptr;
2815 break;
2817 srcptr++;
2822 if(!(*path))
2824 KPRINTF(5, ("Object found: %s\n", dirpoi->poi_Name));
2825 return(dirpoi);
2828 if((dirpoi->poi_ObjectFmt == POF_ASSOCIATION) && (!(dirpoi->poi_Flags & PTPF_FETCHED)))
2830 nLoadDirectory(nch, dirpoi);
2833 while(*path == '/')
2835 KPRINTF(1, ("Going up...\n"));
2836 dirpoi = dirpoi->poi_Parent;
2837 if(!dirpoi)
2839 KPRINTF(5, ("Past root!\n"));
2840 dp->dp_Res2 = ERROR_OBJECT_NOT_FOUND;
2841 return(NULL);
2843 path++;
2846 namehash = nCalcNameHash(nch, path);
2848 if(dirpoi->poi_ObjectFmt == POF_ASSOCIATION)
2850 childpoi = (struct PTPObjectInfo *) dirpoi->poi_Children.mlh_Head;
2851 while(childpoi->poi_Node.mln_Succ)
2853 if(childpoi->poi_NameHash == namehash)
2855 STRPTR tarptr = childpoi->poi_Name;
2856 srcptr = path;
2858 KPRINTF(1, ("Hash matched for %s on %s\n", childpoi->poi_Name, path));
2859 // deep check here
2860 while(*srcptr && *tarptr && (*srcptr != '/'))
2862 if(nch->nch_LowCharMap[*srcptr] != nch->nch_LowCharMap[*tarptr])
2864 break;
2866 srcptr++;
2867 tarptr++;
2869 if(!*tarptr)
2871 KPRINTF(1, ("Exact match!\n"));
2872 dirpoi = childpoi;
2873 if(*srcptr == '/')
2875 // continue after slash
2876 path = srcptr + 1;
2877 } else {
2878 // last component?
2879 path = srcptr;
2881 break;
2882 } else {
2883 KPRINTF(1, ("False positive!\n"));
2886 childpoi = (struct PTPObjectInfo *) childpoi->poi_Node.mln_Succ;
2888 if(!childpoi->poi_Node.mln_Succ)
2890 KPRINTF(5, ("Component %s not found\n", path));
2891 dp->dp_Res2 = ERROR_OBJECT_NOT_FOUND;
2892 return(NULL);
2894 } else {
2895 KPRINTF(10, ("Can't go into file %s for %s\n", dirpoi->poi_Name, path));
2896 dp->dp_Res2 = ERROR_INVALID_COMPONENT_NAME;
2897 return(NULL);
2899 } while(TRUE);
2901 /* \\\ */
2903 /* /// "nGetFileComponent()" */
2904 STRPTR nGetFileComponent(struct NepClassPTP *nch, STRPTR path)
2906 STRPTR srcptr = path;
2907 STRPTR fileptr = path;
2908 STRPTR resptr;
2909 ULONG wordcnt = 0;
2911 while(*srcptr)
2913 if((*srcptr == ':') || (*srcptr == '/'))
2915 fileptr = ++srcptr;
2916 wordcnt = 0;
2917 } else {
2918 ++srcptr;
2919 ++wordcnt;
2923 srcptr = resptr = nAllocVec(nch, wordcnt + 1);
2924 if(resptr)
2926 while((*srcptr++ = *fileptr++));
2928 return(resptr);
2930 /* \\\ */
2932 /* /// "nGetPathComponent()" */
2933 STRPTR nGetPathComponent(struct NepClassPTP *nch, STRPTR path)
2935 STRPTR srcptr = path;
2936 STRPTR fileptr = path;
2937 STRPTR resptr;
2939 while(*srcptr)
2941 if(*srcptr == ':')
2943 fileptr = srcptr + 1;
2945 else if(*srcptr == '/')
2947 fileptr = srcptr;
2949 ++srcptr;
2952 srcptr = resptr = nAllocVec(nch, fileptr - path + 1);
2953 if(resptr)
2955 while(path < fileptr)
2957 *srcptr++ = *path++;
2959 *srcptr = 0;
2961 return(resptr);
2963 /* \\\ */
2965 /* /// "nCreateLock()" */
2966 struct FileLock * nCreateLock(struct NepClassPTP *nch, struct DosPacket *dp, struct PTPObjectInfo *poi, LONG lockmode)
2968 struct FileLock *fl;
2969 if((poi->poi_Flags & PTPF_EXCL_LOCK) || ((lockmode == ACCESS_WRITE) && (poi->poi_Flags & PTPF_SHARED_LOCK)))
2971 KPRINTF(20, ("Can't lock %ld: Object '%s' already locked\n", lockmode, poi->poi_Name));
2972 dp->dp_Res2 = ERROR_OBJECT_IN_USE;
2973 return(NULL);
2975 if(lockmode != ACCESS_WRITE)
2977 lockmode = ACCESS_READ; // workaround for bugged programs
2979 fl = (struct FileLock *) nAllocVec(nch, sizeof(struct FileLock));
2980 if(!fl)
2982 dp->dp_Res2 = ERROR_NO_FREE_STORE;
2983 return(NULL);
2985 KPRINTF(10, ("CreateLock: FL=%08lx for %08lx: '%s' (%s)\n", fl, poi, poi->poi_Name, (lockmode == ACCESS_READ) ? "READ" : "WRITE"));
2986 fl->fl_Link = nch->nch_VolEntry->dol_misc.dol_volume.dol_LockList;
2987 fl->fl_Key = (IPTR) poi;
2988 fl->fl_Access = lockmode;
2989 fl->fl_Task = nch->nch_DOSMsgPort;
2990 fl->fl_Volume = MKBADDR(nch->nch_VolEntry);
2991 if(lockmode == ACCESS_READ)
2993 poi->poi_ReadLocks++;
2994 poi->poi_Flags |= PTPF_SHARED_LOCK;
2995 } else {
2996 poi->poi_Flags |= PTPF_EXCL_LOCK;
2998 nch->nch_VolEntry->dol_misc.dol_volume.dol_LockList = MKBADDR(fl);
2999 return(fl);
3001 /* \\\ */
3003 /* /// "nFreeLock()" */
3004 void nFreeLock(struct NepClassPTP *nch, struct FileLock *fl)
3006 struct PTPObjectInfo *poi;
3007 struct FileLock *headfl;
3009 KPRINTF(1, ("FreeLock(%08lx)\n", fl));
3010 if(!fl)
3012 KPRINTF(10, ("No lock!\n"));
3013 return;
3015 poi = (struct PTPObjectInfo *) fl->fl_Key;
3016 KPRINTF(10, ("Freeing lock on %08lx: '%s'\n", poi, poi->poi_Name));
3017 headfl = (struct FileLock *) BADDR(nch->nch_VolEntry->dol_misc.dol_volume.dol_LockList);
3018 if(headfl == fl)
3020 // head of list
3021 KPRINTF(1, ("Unlinking at head\n"));
3022 nch->nch_VolEntry->dol_misc.dol_volume.dol_LockList = fl->fl_Link;
3023 } else {
3026 if(headfl->fl_Link)
3028 if((struct FileLock *) BADDR(headfl->fl_Link) == fl)
3030 // unlink
3031 KPRINTF(1, ("Unlinking in middle\n"));
3032 headfl->fl_Link = fl->fl_Link;
3033 break;
3035 } else {
3036 KPRINTF(20, ("LOCK NOT FOUND IN LIST!\n"));
3037 break;
3039 headfl = (struct FileLock *) BADDR(headfl->fl_Link);
3040 } while(TRUE);
3043 nFreeVec(nch, fl);
3044 if(poi->poi_Flags & PTPF_SHARED_LOCK)
3046 if(!(--poi->poi_ReadLocks))
3048 poi->poi_Flags &= ~PTPF_SHARED_LOCK;
3050 } else {
3051 poi->poi_Flags &= ~PTPF_EXCL_LOCK;
3054 /* \\\ */
3056 /* /// "nCreateFH()" */
3057 struct PTPFileHandle * nCreateFH(struct NepClassPTP *nch, struct DosPacket *dp, struct PTPObjectInfo *poi, LONG lockmode)
3059 struct PTPFileHandle *pfh;
3060 if((poi->poi_Flags & PTPF_EXCL_LOCK) || ((lockmode == ACCESS_WRITE) && (poi->poi_Flags & PTPF_SHARED_LOCK)))
3062 KPRINTF(20, ("Can't open %ld: Object '%s' already locked\n", lockmode, poi->poi_Name));
3063 dp->dp_Res2 = ERROR_OBJECT_IN_USE;
3064 return(NULL);
3066 pfh = (struct PTPFileHandle *) nAllocVec(nch, sizeof(struct PTPFileHandle));
3067 if(!pfh)
3069 dp->dp_Res2 = ERROR_NO_FREE_STORE;
3070 return(NULL);
3072 KPRINTF(10, ("CreateFH: FH=%08lx for %08lx: '%s'\n", pfh, poi, poi->poi_Name));
3073 pfh->pfh_ObjectInfo = poi;
3074 if(lockmode == ACCESS_READ)
3076 poi->poi_ReadLocks++;
3077 poi->poi_Flags |= PTPF_SHARED_LOCK;
3078 } else {
3079 poi->poi_Flags |= PTPF_EXCL_LOCK;
3081 AddTail(&nch->nch_FHs, &pfh->pfh_Node);
3082 return(pfh);
3084 /* \\\ */
3086 /* /// "nFreeFH()" */
3087 void nFreeFH(struct NepClassPTP *nch, struct PTPFileHandle *pfh)
3089 struct PTPObjectInfo *poi;
3091 KPRINTF(1, ("FreeFH(%08lx)\n", pfh));
3092 if(!pfh)
3094 KPRINTF(10, ("No FH!\n"));
3095 return;
3097 Remove(&pfh->pfh_Node);
3098 nFreeVec(nch, pfh->pfh_Buffer);
3099 poi = pfh->pfh_ObjectInfo;
3100 nFreeVec(nch, pfh);
3101 if(poi->poi_Flags & PTPF_SHARED_LOCK)
3103 if(!(--poi->poi_ReadLocks))
3105 poi->poi_Flags &= ~PTPF_SHARED_LOCK;
3107 } else {
3108 poi->poi_Flags &= ~PTPF_EXCL_LOCK;
3111 /* \\\ */
3113 /* /// "defaultObjectMapping" */
3114 static struct ObjectFmtMapping defaultObjectMapping[] =
3116 { POF_SCRIPT, "sh" },
3117 { POF_SCRIPT, "bat" },
3118 { POF_EXECUTABLE, "exe" },
3119 { POF_TEXT, "txt" },
3120 { POF_HTML, "htm" },
3121 { POF_HTML, "html" },
3122 { POF_DPOF, "dps" },
3123 { POF_AIFF, "aiff" },
3124 { POF_WAV, "wav" },
3125 { POF_MP3, "mp3" },
3126 { POF_AVI, "avi" },
3127 { POF_MPEG, "mpg" },
3128 { POF_MPEG, "mpeg" },
3129 { POF_ASF, "asf" },
3130 { POF_EXIF_JPEG, "jpg" },
3131 { POF_EXIF_JPEG, "jpeg" },
3132 { POF_TIFF, "tif" },
3133 { POF_TIFF, "tiff" },
3134 { POF_BMP, "bmp" },
3135 { POF_GIF, "gif" },
3136 { POF_JFIF, "jfif" },
3137 { POF_PCD, "pcd" },
3138 { POF_PICT, "pct" },
3139 { POF_PNG, "png" },
3140 { POF_JP2, "jp2" },
3141 { POF_JPX, "jpx" },
3142 { 0, NULL }
3144 /* \\\ */
3146 /* /// "nGetFormatFromName()" */
3147 UWORD nGetFormatFromName(struct NepClassPTP *nch, STRPTR name)
3149 STRPTR suffix = NULL;
3150 struct ObjectFmtMapping *ofm = defaultObjectMapping;
3151 while(*name)
3153 if(*name++ == '.')
3155 suffix = name;
3158 if(!suffix)
3160 return POF_UNDEFINED;
3162 while(ofm->ofm_ID)
3164 if(stricmp(suffix, ofm->ofm_Suffix) == 0)
3166 return ofm->ofm_ID;
3168 ofm++;
3170 return POF_UNDEFINED;
3172 /* \\\ */
3174 /* /// "nHandleDOSPackets()" */
3175 void nHandleDOSPackets(struct NepClassPTP *nch)
3177 struct Message *mn;
3178 struct MsgPort *replyport;
3179 struct DosPacket *dp;
3180 UBYTE buf[256];
3182 struct PTPObjectInfo *parentdir;
3183 struct PTPObjectInfo *poi;
3184 struct PTPFileHandle *pfh;
3185 UBYTE *tmpbstr;
3186 LONG lockmode;
3187 struct FileLock *fl;
3188 struct FileInfoBlock *fib;
3189 struct InfoData *id;
3190 struct FileHandle *fh;
3191 UWORD cnt;
3192 UBYTE *srcptr;
3193 UBYTE *tarptr;
3195 while((mn = GetMsg(nch->nch_DOSMsgPort)))
3197 KPRINTF(1, ("DOS Packet arrived %08lx!\n", mn));
3198 dp = (struct DosPacket *) mn->mn_Node.ln_Name;
3199 dp->dp_Res1 = DOSTRUE;
3200 dp->dp_Res2 = 0;
3202 KPRINTF(10, ("**** Action %ld: Arg1=%08lx Arg2=%08lx Arg3=%08lx\n",
3203 dp->dp_Action, dp->dp_Arg1, dp->dp_Arg2, dp->dp_Arg3));
3205 switch(dp->dp_Action)
3207 case ACTION_DIE:
3208 nch->nch_ShallExit = TRUE;
3209 break;
3211 // no-ops
3212 case ACTION_FLUSH:
3213 nch->nch_LastObject = NULL; // Invalidate last object
3214 nFreeVec(nch, nch->nch_LastBuffer);
3215 nch->nch_LastBuffer = NULL;
3216 // fall through
3217 case ACTION_INHIBIT:
3219 case ACTION_IS_FILESYSTEM:
3220 // returns DOSTRUE
3221 break;
3223 case ACTION_SAME_LOCK:
3224 dp->dp_Res1 = (nGetObjFromLock(nch, (BPTR) dp->dp_Arg1) == nGetObjFromLock(nch, (BPTR) dp->dp_Arg2)) ? DOSTRUE : DOSFALSE;
3225 break;
3227 case ACTION_FORMAT:
3228 nch->nch_LastObject = NULL; // Invalidate last object
3229 nFreeVec(nch, nch->nch_LastBuffer);
3230 nch->nch_LastBuffer = NULL;
3231 nPTPFormatStore(nch, dp);
3232 break;
3234 case ACTION_CURRENT_VOLUME:
3235 dp->dp_Res1 = (SIPTR) MKBADDR(nch->nch_VolEntry);
3236 dp->dp_Res2 = 0;
3237 break;
3239 case ACTION_INFO:
3240 case ACTION_DISK_INFO:
3242 struct PTPStorageInfo *psi;
3243 ULONG numblocks = 0;
3244 ULONG numfree = 0;
3245 ULONG storageid = 0;
3246 ULONG bitshift = 9;
3247 if(dp->dp_Action == ACTION_INFO)
3249 poi = nGetObjFromLock(nch, (BPTR) dp->dp_Arg1);
3250 id = (struct InfoData *) BADDR(dp->dp_Arg2);
3251 storageid = poi->poi_StorageID;
3252 } else {
3253 id = (struct InfoData *) BADDR(dp->dp_Arg1);
3255 // determine bit shift value for optimal blocksize
3256 psi = (struct PTPStorageInfo *) nch->nch_Storages.lh_Head;
3257 while(psi->psi_Node.ln_Succ)
3259 if(psi->psi_MaxCapacityH != 0xffffffff)
3261 while((bitshift < 24) && psi->psi_MaxCapacityH>>(bitshift-2))
3263 bitshift++;
3266 psi = (struct PTPStorageInfo *) psi->psi_Node.ln_Succ;
3268 KPRINTF(5, ("Bitshift %ld\n", bitshift));
3269 psi = (struct PTPStorageInfo *) nch->nch_Storages.lh_Head;
3270 while(psi->psi_Node.ln_Succ)
3272 if((storageid == psi->psi_StorageID) || (!storageid))
3274 if(psi->psi_MaxCapacityH>>15)
3276 numblocks = 0x3fffff; // avoid overflow
3277 numfree = 0x3fffff;
3278 bitshift = 9;
3279 break;
3281 numblocks += (psi->psi_MaxCapacityL>>bitshift)|(psi->psi_MaxCapacityH<<(32-bitshift));
3282 numfree += (psi->psi_FreeL>>bitshift)|(psi->psi_FreeH<<(32-bitshift));
3283 KPRINTF(5, ("Blocks %ld free of %ld\n", numfree, numblocks));
3285 psi = (struct PTPStorageInfo *) psi->psi_Node.ln_Succ;
3287 if(!numblocks)
3289 if(numfree)
3291 numblocks = numfree;
3292 } else {
3293 numblocks = 1; // make sure we don't get division by zero errors
3296 if(numfree > numblocks)
3298 numfree = numblocks;
3300 //numblocks = 1000;
3301 //numfree = 500;
3302 //bitshift = 9;
3303 id->id_NumSoftErrors = 0;
3304 id->id_UnitNumber = 0;
3305 id->id_DiskState = ID_VALIDATED;
3306 id->id_NumBlocks = numblocks;
3307 id->id_NumBlocksUsed = numblocks - numfree;
3308 id->id_BytesPerBlock = 1<<bitshift;
3309 id->id_DiskType = ID_DOS_DISK;
3310 id->id_VolumeNode = MKBADDR(nch->nch_VolEntry);
3311 id->id_InUse = nch->nch_VolEntry->dol_misc.dol_volume.dol_LockList ? DOSTRUE : DOSFALSE;
3312 break;
3315 case ACTION_FINDINPUT:
3316 case ACTION_FINDUPDATE:
3317 fh = (struct FileHandle *) BADDR(dp->dp_Arg1);
3318 parentdir = nGetObjFromLock(nch, (BPTR) dp->dp_Arg2);
3319 tmpbstr = (UBYTE *) BADDR(dp->dp_Arg3);
3320 b2cstr(tmpbstr, buf);
3322 KPRINTF(5, ("OpenOld Object '%s', Parent=%s\n", buf, parentdir->poi_Name));
3323 poi = nSearchObject(nch, dp, parentdir, buf);
3324 if(poi)
3326 if(poi->poi_ObjectFmt == POF_ASSOCIATION)
3328 dp->dp_Res2 = ERROR_OBJECT_WRONG_TYPE;
3329 break;
3331 pfh = nCreateFH(nch, dp, poi, ACCESS_READ);
3332 if(!pfh)
3334 break;
3336 fh->fh_Arg1 = (IPTR)pfh;
3337 break;
3338 } else {
3339 if(dp->dp_Action == ACTION_FINDINPUT)
3341 break;
3343 KPRINTF(5, ("OpenReadWrite Object '%s', Parent=%s\n", buf, parentdir->poi_Name));
3344 dp->dp_Res2 = 0;
3345 // fall through
3348 case ACTION_FINDOUTPUT:
3349 if(!(nch->nch_DevCaps & PTPF_SENDOBJ))
3351 dp->dp_Res2 = ERROR_DISK_WRITE_PROTECTED;
3352 break;
3354 fh = (struct FileHandle *) BADDR(dp->dp_Arg1);
3355 parentdir = nGetObjFromLock(nch, (BPTR) dp->dp_Arg2);
3356 tmpbstr = (UBYTE *) BADDR(dp->dp_Arg3);
3357 b2cstr(tmpbstr, buf);
3358 if(dp->dp_Action == ACTION_FINDOUTPUT)
3360 KPRINTF(5, ("OpenNew Object '%s', Parent=%s\n", buf, parentdir->poi_Name));
3361 poi = nSearchObject(nch, dp, parentdir, buf);
3362 if(poi)
3364 // delete old file first
3365 if(poi->poi_Flags & (PTPF_EXCL_LOCK|PTPF_SHARED_LOCK))
3367 dp->dp_Res2 = ERROR_OBJECT_IN_USE;
3368 break;
3370 if(poi->poi_ObjectFmt == POF_ASSOCIATION)
3372 dp->dp_Res2 = ERROR_OBJECT_WRONG_TYPE;
3373 break;
3375 if(poi->poi_Handle == 0xffffffff) // cannot delete volume
3377 dp->dp_Res2 = ERROR_DIR_NOT_FOUND;
3378 break;
3380 nPTPDeleteObject(nch, dp, poi);
3381 if(!dp->dp_Res2)
3383 Remove((struct Node *) poi);
3384 nPTPFreeObjectInfo(nch, poi);
3385 nch->nch_LastObject = NULL; // Invalidate last object
3386 nFreeVec(nch, nch->nch_LastBuffer);
3387 nch->nch_LastBuffer = NULL;
3389 DateStamp(&poi->poi_Parent->poi_ModDate);
3390 } else {
3391 break;
3395 dp->dp_Res2 = 0;
3396 srcptr = nGetPathComponent(nch, buf);
3397 if(!srcptr)
3399 dp->dp_Res2 = ERROR_NO_FREE_STORE;
3400 break;
3402 parentdir = nSearchObject(nch, dp, parentdir, srcptr);
3403 nFreeVec(nch, srcptr);
3404 if(!parentdir)
3406 break;
3408 KPRINTF(10, ("Parent dir for new file: %s\n", parentdir->poi_Name));
3409 if(parentdir->poi_StorageID == 0xffffffff) // cannot create files on root level
3411 dp->dp_Res2 = ERROR_DIR_NOT_FOUND;
3412 break;
3414 poi = nAllocVec(nch, sizeof(struct PTPObjectInfo));
3415 if(!poi)
3417 dp->dp_Res2 = ERROR_NO_FREE_STORE;
3418 break;
3420 NewList((struct List *) &poi->poi_Children);
3421 poi->poi_Handle = 0;
3422 poi->poi_StorageID = parentdir->poi_StorageID;
3423 poi->poi_ProtFlags = FIBF_READ|FIBF_WRITE|FIBF_DELETE;
3424 poi->poi_Size = 0;
3425 poi->poi_Parent = parentdir;
3426 poi->poi_ParentHandle = parentdir->poi_Handle;
3427 poi->poi_Name = nGetFileComponent(nch, buf);
3428 if(!poi->poi_Name)
3430 nFreeVec(nch, poi);
3431 dp->dp_Res2 = ERROR_NO_FREE_STORE;
3432 break;
3434 poi->poi_ObjectFmt = nGetFormatFromName(nch, poi->poi_Name);
3435 KPRINTF(10, ("Determined object format: %02lx\n", poi->poi_ObjectFmt));
3437 DateStamp(&poi->poi_CapDate);
3438 DateStamp(&poi->poi_ModDate);
3439 poi->poi_NameHash = nCalcNameHash(nch, poi->poi_Name);
3441 pfh = nCreateFH(nch, dp, poi, ACCESS_WRITE);
3442 if(!pfh)
3444 nPTPFreeObjectInfo(nch, poi);
3445 break;
3447 pfh->pfh_Flags |= PTPF_NEWFILE|PTPF_MODIFIED;
3448 fh->fh_Arg1 = (IPTR) pfh;
3449 AddTail((struct List *) &parentdir->poi_Children, (struct Node *) poi);
3450 break;
3452 #if 1 // currently no way to create directories according to PTP spec
3453 case ACTION_CREATE_DIR:
3454 if(!(nch->nch_DevCaps & PTPF_SENDOBJ))
3456 dp->dp_Res2 = ERROR_DISK_WRITE_PROTECTED;
3457 break;
3459 parentdir = nGetObjFromLock(nch, (BPTR) dp->dp_Arg1);
3460 tmpbstr = (UBYTE *) BADDR(dp->dp_Arg2);
3461 b2cstr(tmpbstr, buf);
3462 KPRINTF(5, ("MakeDir '%s', Parent=%s\n", buf, parentdir->poi_Name));
3463 poi = nSearchObject(nch, dp, parentdir, buf);
3464 if(poi)
3466 dp->dp_Res2 = ERROR_OBJECT_EXISTS;
3467 break;
3469 dp->dp_Res2 = 0;
3470 srcptr = nGetPathComponent(nch, buf);
3471 if(!srcptr)
3473 dp->dp_Res2 = ERROR_NO_FREE_STORE;
3474 break;
3476 parentdir = nSearchObject(nch, dp, parentdir, srcptr);
3477 nFreeVec(nch, srcptr);
3478 if(!parentdir)
3480 break;
3482 KPRINTF(10, ("Parent dir for new directory: %s\n", parentdir->poi_Name));
3483 if(parentdir->poi_StorageID == 0xffffffff) // cannot create directories on root level
3485 dp->dp_Res2 = ERROR_DIR_NOT_FOUND;
3486 break;
3488 poi = nAllocVec(nch, sizeof(struct PTPObjectInfo));
3489 if(!poi)
3491 dp->dp_Res2 = ERROR_NO_FREE_STORE;
3492 break;
3494 NewList((struct List *) &poi->poi_Children);
3495 poi->poi_Handle = 0;
3496 poi->poi_StorageID = parentdir->poi_StorageID;
3497 poi->poi_ProtFlags = FIBF_READ|FIBF_WRITE|FIBF_DELETE;
3498 poi->poi_Size = 0;
3499 poi->poi_Parent = parentdir;
3500 poi->poi_ParentHandle = parentdir->poi_Handle;
3501 poi->poi_Name = nGetFileComponent(nch, buf);
3502 if(!poi->poi_Name)
3504 nFreeVec(nch, poi);
3505 dp->dp_Res2 = ERROR_NO_FREE_STORE;
3506 break;
3508 poi->poi_ObjectFmt = POF_ASSOCIATION;
3510 DateStamp(&poi->poi_CapDate);
3511 DateStamp(&poi->poi_ModDate);
3512 poi->poi_NameHash = nCalcNameHash(nch, poi->poi_Name);
3514 KPRINTF(10, ("Sending Object for MakeDir\n"));
3515 if(!(nPTPSendObject(nch, dp, poi, NULL)))
3517 nPTPFreeObjectInfo(nch, poi);
3518 } else {
3519 AddTail((struct List *) &parentdir->poi_Children, (struct Node *) poi);
3520 fl = nCreateLock(nch, dp, poi, ACCESS_WRITE);
3521 if(fl)
3523 dp->dp_Res1 = (SIPTR) MKBADDR(fl);
3524 KPRINTF(1, ("Copied lock %08lx\n", dp->dp_Res1));
3527 break;
3528 #endif
3530 case ACTION_FH_FROM_LOCK:
3531 fh = (struct FileHandle *) BADDR(dp->dp_Arg1);
3532 fl = (struct FileLock *) BADDR(dp->dp_Arg2);
3533 poi = nGetObjFromLock(nch, (BPTR) dp->dp_Arg2);
3534 lockmode = fl->fl_Access;
3536 KPRINTF(5, ("OpenFromLock Object '%s'\n", poi->poi_Name));
3537 if(poi->poi_ObjectFmt == POF_ASSOCIATION)
3539 dp->dp_Res2 = ERROR_OBJECT_WRONG_TYPE;
3540 break;
3542 if(lockmode == ACCESS_WRITE)
3544 if(!(nch->nch_DevCaps & PTPF_SENDOBJ))
3546 dp->dp_Res2 = ERROR_DISK_WRITE_PROTECTED;
3547 break;
3549 poi->poi_Flags &= ~PTPF_EXCL_LOCK;
3550 pfh = nCreateFH(nch, dp, poi, ACCESS_WRITE);
3551 if(!pfh)
3553 poi->poi_Flags |= PTPF_EXCL_LOCK;
3554 break;
3556 nFreeLock(nch, fl);
3557 poi->poi_Flags |= PTPF_EXCL_LOCK;
3558 } else {
3559 pfh = nCreateFH(nch, dp, poi, ACCESS_READ);
3560 if(!pfh)
3562 break;
3564 nFreeLock(nch, fl);
3566 pfh->pfh_SeekPos = 0;
3567 fh->fh_Arg1 = (IPTR)pfh;
3568 break;
3570 case ACTION_END:
3571 pfh = (struct PTPFileHandle *) dp->dp_Arg1;
3572 KPRINTF(10, ("Closing File %s\n", pfh->pfh_ObjectInfo->poi_Name));
3573 if(pfh->pfh_Flags & PTPF_MODIFIED)
3575 KPRINTF(10, ("Modified, needs updating on device\n"));
3576 if(!(pfh->pfh_Flags & PTPF_NEWFILE))
3578 KPRINTF(10, ("Deleting old object first\n"));
3579 nPTPDeleteObject(nch, dp, pfh->pfh_ObjectInfo);
3580 if(dp->dp_Res2)
3582 break;
3585 KPRINTF(10, ("Sending Object\n"));
3586 if(!(nPTPSendObject(nch, dp, pfh->pfh_ObjectInfo, pfh->pfh_Buffer)))
3588 Remove((struct Node *) pfh->pfh_ObjectInfo);
3589 nPTPFreeObjectInfo(nch, pfh->pfh_ObjectInfo);
3590 nFreeVec(nch, pfh->pfh_Buffer);
3591 pfh->pfh_Buffer = NULL;
3594 if(pfh->pfh_Buffer)
3596 nch->nch_LastObject = pfh->pfh_ObjectInfo; // New last object cache
3597 nFreeVec(nch, nch->nch_LastBuffer);
3598 nch->nch_LastBuffer = pfh->pfh_Buffer;
3599 nch->nch_LastBufferLen = pfh->pfh_BufferLen;
3600 pfh->pfh_Buffer = NULL;
3602 nFreeFH(nch, pfh);
3603 break;
3605 case ACTION_SEEK:
3607 LONG relpos = dp->dp_Arg2;
3608 LONG mode = dp->dp_Arg3;
3609 ULONG newpos;
3611 pfh = (struct PTPFileHandle *) dp->dp_Arg1;
3612 newpos = dp->dp_Res1 = pfh->pfh_SeekPos;
3613 poi = pfh->pfh_ObjectInfo;
3614 switch(mode)
3616 case OFFSET_END:
3617 newpos = poi->poi_Size + relpos;
3618 KPRINTF(10, ("Seek from end %ld: %ld\n", relpos, newpos));
3619 break;
3621 case OFFSET_CURRENT:
3622 newpos += relpos;
3623 KPRINTF(10, ("Seek from current %ld: %ld\n", relpos, newpos));
3624 break;
3626 case OFFSET_BEGINNING:
3627 newpos = relpos;
3628 KPRINTF(10, ("Seek from beginning %ld\n", relpos));
3629 break;
3631 default:
3632 dp->dp_Res2 = ERROR_SEEK_ERROR;
3633 break;
3636 if(newpos > poi->poi_Size)
3638 dp->dp_Res2 = ERROR_SEEK_ERROR;
3641 pfh->pfh_SeekPos = newpos;
3642 break;
3645 case ACTION_READ:
3646 pfh = (struct PTPFileHandle *) dp->dp_Arg1;
3647 nPTPRead(nch, dp, pfh, (UBYTE *) dp->dp_Arg2, (ULONG) dp->dp_Arg3);
3648 break;
3650 case ACTION_WRITE:
3651 if(!(nch->nch_DevCaps & PTPF_SENDOBJ))
3653 dp->dp_Res2 = ERROR_DISK_WRITE_PROTECTED;
3654 break;
3656 pfh = (struct PTPFileHandle *) dp->dp_Arg1;
3657 if(pfh->pfh_ObjectInfo->poi_ProtFlags & FIBF_WRITE)
3659 nPTPWrite(nch, dp, pfh, (UBYTE *) dp->dp_Arg2, (ULONG) dp->dp_Arg3);
3660 } else {
3661 dp->dp_Res2 = ERROR_WRITE_PROTECTED;
3663 break;
3665 case ACTION_SET_PROTECT:
3667 ULONG protflags;
3668 if(!(nch->nch_DevCaps & PTPF_PROTOBJ))
3670 dp->dp_Res2 = ERROR_DISK_WRITE_PROTECTED;
3671 break;
3673 parentdir = nGetObjFromLock(nch, (BPTR) dp->dp_Arg2);
3674 protflags = dp->dp_Arg4 ^ (FIBF_READ|FIBF_WRITE|FIBF_DELETE|FIBF_EXECUTE);
3675 tmpbstr = (UBYTE *) BADDR(dp->dp_Arg3);
3676 b2cstr(tmpbstr, buf);
3678 KPRINTF(5, ("Set Protect '%s', Parent=%s\n", buf, parentdir->poi_Name));
3679 poi = nSearchObject(nch, dp, parentdir, buf);
3680 if(poi)
3682 nPTPSetObjectProtection(nch, dp, poi, protflags);
3684 break;
3687 case ACTION_DELETE_OBJECT:
3688 if(!(nch->nch_DevCaps & PTPF_DELETEOBJ))
3690 dp->dp_Res2 = ERROR_DELETE_PROTECTED;
3691 break;
3693 parentdir = nGetObjFromLock(nch, (BPTR) dp->dp_Arg1);
3694 tmpbstr = (UBYTE *) BADDR(dp->dp_Arg2);
3695 b2cstr(tmpbstr, buf);
3697 KPRINTF(5, ("DeleteObject '%s', Parent=%s\n", buf, parentdir->poi_Name));
3698 poi = nSearchObject(nch, dp, parentdir, buf);
3699 if(poi)
3701 if(poi->poi_Flags & (PTPF_EXCL_LOCK|PTPF_SHARED_LOCK))
3703 dp->dp_Res2 = ERROR_OBJECT_IN_USE;
3704 break;
3706 if(poi->poi_Children.mlh_Head->mln_Succ)
3708 dp->dp_Res2 = ERROR_DIRECTORY_NOT_EMPTY;
3709 break;
3711 if(poi->poi_Handle == 0xffffffff)
3713 dp->dp_Res2 = ERROR_DIRECTORY_NOT_EMPTY;
3714 break;
3716 if(!(poi->poi_ProtFlags & FIBF_DELETE))
3718 dp->dp_Res2 = ERROR_DELETE_PROTECTED;
3719 break;
3721 nPTPDeleteObject(nch, dp, poi);
3722 if(!dp->dp_Res2)
3724 DateStamp(&poi->poi_Parent->poi_ModDate);
3725 Remove((struct Node *) poi);
3726 nPTPFreeObjectInfo(nch, poi);
3727 nch->nch_LastObject = NULL; // Invalidate last object
3728 nFreeVec(nch, nch->nch_LastBuffer);
3729 nch->nch_LastBuffer = NULL;
3732 break;
3734 case ACTION_RENAME_OBJECT:
3736 struct PTPObjectInfo *targetdir;
3737 ULONG cnt;
3739 if(!(nch->nch_DevCaps & PTPF_MOVEOBJ))
3741 dp->dp_Res2 = ERROR_DISK_WRITE_PROTECTED;
3742 break;
3745 srcptr = (UBYTE *) BADDR(dp->dp_Arg2);
3746 tarptr = (UBYTE *) BADDR(dp->dp_Arg4);
3747 cnt = *srcptr;
3748 if(*srcptr++ != *tarptr++)
3750 // length mismatch
3751 KPRINTF(10, ("RenameObject failed: Name lengths different!\n"));
3752 dp->dp_Res2 = ERROR_RENAME_ACROSS_DEVICES;
3753 break;
3755 if(!cnt)
3757 dp->dp_Res2 = ERROR_INVALID_COMPONENT_NAME;
3758 break;
3762 if(*srcptr++ != *tarptr++)
3764 KPRINTF(10, ("RenameObject failed: Names different!\n"));
3765 dp->dp_Res2 = ERROR_RENAME_ACROSS_DEVICES;
3766 break;
3768 } while(--cnt);
3769 if(!dp->dp_Res2)
3771 break;
3774 parentdir = nGetObjFromLock(nch, (BPTR) dp->dp_Arg1);
3775 targetdir = nGetObjFromLock(nch, (BPTR) dp->dp_Arg3);
3777 poi = nSearchObject(nch, dp, parentdir, buf);
3778 if(poi)
3780 KPRINTF(10, ("RenameObject moving %s from %s to %s.\n", poi->poi_Name, parentdir->poi_Name, targetdir->poi_Name));
3781 if(parentdir != targetdir)
3783 nPTPMoveObject(nch, dp, poi, targetdir);
3786 break;
3789 case ACTION_PARENT_FH:
3790 case ACTION_PARENT:
3791 if(dp->dp_Action == ACTION_PARENT)
3793 poi = nGetObjFromLock(nch, (BPTR) dp->dp_Arg1);
3794 } else {
3795 pfh = (struct PTPFileHandle *) dp->dp_Arg1;
3796 poi = pfh->pfh_ObjectInfo;
3798 if(poi->poi_Parent)
3800 fl = nCreateLock(nch, dp, poi->poi_Parent, ACCESS_READ);
3801 if(fl)
3803 dp->dp_Res1 = (SIPTR) MKBADDR(fl);
3804 KPRINTF(1, ("Found parent %08lx\n", dp->dp_Res1));
3806 } else {
3807 dp->dp_Res1 = (SIPTR) NULL;
3808 // don't set an error code!
3810 break;
3812 case ACTION_COPY_DIR_FH:
3813 case ACTION_COPY_DIR:
3814 if(dp->dp_Action == ACTION_COPY_DIR)
3816 poi = nGetObjFromLock(nch, (BPTR) dp->dp_Arg1);
3817 } else {
3818 pfh = (struct PTPFileHandle *) dp->dp_Arg1;
3819 poi = pfh->pfh_ObjectInfo;
3821 fl = nCreateLock(nch, dp, poi, ACCESS_READ);
3822 if(fl)
3824 dp->dp_Res1 = (SIPTR) MKBADDR(fl);
3825 KPRINTF(1, ("Copied lock %08lx\n", dp->dp_Res1));
3827 break;
3829 case ACTION_LOCATE_OBJECT:
3830 parentdir = nGetObjFromLock(nch, (BPTR) dp->dp_Arg1);
3831 tmpbstr = (UBYTE *) BADDR(dp->dp_Arg2);
3832 lockmode = dp->dp_Arg3;
3833 b2cstr(tmpbstr, buf);
3835 KPRINTF(5, ("Locate Object '%s', Parent=%s\n", buf, parentdir->poi_Name));
3836 poi = nSearchObject(nch, dp, parentdir, buf);
3837 if(poi)
3839 fl = nCreateLock(nch, dp, poi, lockmode);
3840 if(fl)
3842 dp->dp_Res1 = (SIPTR) MKBADDR(fl);
3843 KPRINTF(1, ("Found %08lx\n", dp->dp_Res1));
3846 break;
3848 case ACTION_EXAMINE_NEXT:
3849 case ACTION_EXAMINE_OBJECT:
3850 case ACTION_EXAMINE_FH:
3851 fib = (struct FileInfoBlock *) BADDR(dp->dp_Arg2);
3852 if(!fib)
3853 KPRINTF(1, ("FIB: %08lx\n", fib));
3854 if(dp->dp_Action != ACTION_EXAMINE_FH)
3856 poi = nGetObjFromLock(nch, (BPTR) dp->dp_Arg1);
3857 if(dp->dp_Action == ACTION_EXAMINE_NEXT)
3859 KPRINTF(5, ("ExamineNext: '%s'\n", poi->poi_Name));
3860 if(poi->poi_ObjectFmt != POF_ASSOCIATION)
3862 dp->dp_Res2 = ERROR_OBJECT_WRONG_TYPE;
3863 break;
3865 if(!(poi->poi_Flags & PTPF_FETCHED))
3867 nLoadDirectory(nch, poi);
3869 // get next child
3870 poi = (struct PTPObjectInfo *) ((struct PTPObjectInfo *) fib->fib_DiskKey)->poi_Node.mln_Succ;
3871 if(!poi->poi_Node.mln_Succ)
3873 dp->dp_Res2 = ERROR_NO_MORE_ENTRIES;
3874 break;
3876 KPRINTF(1, ("Child: %s\n", poi->poi_Name));
3877 fib->fib_DiskKey = (IPTR) poi;
3878 } else {
3879 KPRINTF(5, ("Examine (%08lx): '%s'\n", poi, poi->poi_Name));
3880 fib->fib_DiskKey = (IPTR) &poi->poi_Children;
3882 } else {
3883 pfh = (struct PTPFileHandle *) dp->dp_Arg1;
3884 poi = pfh->pfh_ObjectInfo;
3886 if(!poi->poi_Parent)
3888 fib->fib_DirEntryType = ST_ROOT;
3889 } else {
3890 fib->fib_DirEntryType = (poi->poi_ObjectFmt == POF_ASSOCIATION) ? ST_USERDIR : ST_FILE;
3892 cnt = 0;
3893 srcptr = poi->poi_Name;
3894 tarptr = fib->fib_FileName + 1;
3895 while((*tarptr++ = *srcptr++))
3897 if(++cnt > 106)
3899 break;
3902 fib->fib_FileName[0] = cnt;
3903 fib->fib_Protection = poi->poi_ProtFlags ^ (FIBF_READ|FIBF_WRITE|FIBF_DELETE|FIBF_EXECUTE);
3904 fib->fib_EntryType = fib->fib_DirEntryType;
3905 fib->fib_Size = poi->poi_Size;
3906 fib->fib_NumBlocks = (poi->poi_Size + 65535)>>16;
3907 fib->fib_Date = poi->poi_ModDate;
3908 if(poi->poi_Keywords)
3910 cnt = 0;
3911 srcptr = poi->poi_Keywords;
3912 tarptr = fib->fib_Comment + 1;
3913 while((*tarptr++ = *srcptr++))
3915 if(++cnt > 78)
3917 break;
3920 fib->fib_Comment[0] = cnt;
3922 /*fib->fib_OwnerUID = 0;
3923 fib->fib_OwnerGID = 0;*/
3924 break;
3926 case ACTION_FREE_LOCK:
3927 fl = (struct FileLock *) BADDR(dp->dp_Arg1);
3928 nFreeLock(nch, fl);
3929 break;
3931 default:
3932 KPRINTF(10, ("**** UNKNOWN Action %ld: Arg1=%08lx Arg2=%08lx Arg3=%08lx\n",
3933 dp->dp_Action, dp->dp_Arg1, dp->dp_Arg2, dp->dp_Arg3));
3934 dp->dp_Res2 = ERROR_ACTION_NOT_KNOWN;
3935 break;
3938 if(dp->dp_Res2)
3940 dp->dp_Res1 = DOSFALSE;
3942 KPRINTF(10, ("**** Return: %08lx, Error: %ld\n\n", dp->dp_Res1, dp->dp_Res2));
3944 replyport = dp->dp_Port;
3945 dp->dp_Port = nch->nch_DOSMsgPort;
3946 mn = dp->dp_Link;
3947 mn->mn_Node.ln_Name = (STRPTR) dp;
3948 mn->mn_Node.ln_Pred = mn->mn_Node.ln_Succ = NULL;
3949 PutMsg(replyport, mn);
3952 /* \\\ */
3954 /* /// "nPTPTask()" */
3955 AROS_UFH0(void, nPTPTask)
3957 AROS_USERFUNC_INIT
3959 struct NepClassPTP *nch;
3960 //struct PsdPipe *pp;
3961 ULONG sigmask;
3962 ULONG sigs;
3963 //UBYTE eventbuf[24];
3964 //LONG ioerr;
3965 //ULONG pktlen;
3966 BOOL reportlocks = TRUE;
3967 BOOL reportfhs = TRUE;
3969 if((nch = nAllocPTP()))
3971 Forbid();
3972 if(nch->nch_ReadySigTask)
3974 Signal(nch->nch_ReadySigTask, 1L<<nch->nch_ReadySignal);
3976 Permit();
3977 sigmask = (1L<<nch->nch_TaskMsgPort->mp_SigBit)|(1L<<nch->nch_DOSMsgPort->mp_SigBit)|SIGBREAKF_CTRL_C;
3979 nch->nch_SessionID = 0;
3980 nch->nch_TransID = 0;
3981 nch->nch_ShallExit = FALSE;
3983 nPTPGetDeviceInfo(nch);
3984 nPTPOpenSession(nch);
3987 ULONG *ids = nPTPGetStorageIDs(nch);
3988 ULONG cnt;
3989 ULONG storageid;
3990 struct PTPStorageInfo *psi;
3991 if(ids)
3993 cnt = ids[0];
3994 KPRINTF(10, ("%ld StorageIDs:\n", cnt));
3995 while(cnt)
3997 storageid = ids[ids[0] - cnt + 1];
3998 KPRINTF(1, ("%ld: StorageID %08lx\n", ids[0] - cnt, storageid));
3999 psi = nPTPGetStorageInfo(nch, storageid);
4000 AddTail(&nch->nch_Storages, &psi->psi_Node);
4001 cnt--;
4003 nFreeVec(nch, ids);
4008 STRPTR devname;
4009 struct DosList *dol;
4010 dol = nch->nch_DevEntry;
4011 dol->dol_Next = 0;
4012 dol->dol_Type = DLT_DEVICE;
4013 dol->dol_Task = nch->nch_DOSMsgPort;
4014 dol->dol_Lock = 0;
4015 dol->dol_misc.dol_handler.dol_Handler = 0;
4016 dol->dol_misc.dol_handler.dol_StackSize = 4096;
4017 dol->dol_misc.dol_handler.dol_Priority = 10;
4018 dol->dol_misc.dol_handler.dol_Startup = 0;
4019 //dol->dol_misc.dol_handler.dol_SegList = 0; // AROS does not have these two fields
4020 //dol->dol_misc.dol_handler.dol_GlobVec = -1;
4021 devname = (STRPTR) (dol + 1);
4022 c2bstr(nch->nch_CDC->cdc_DOSName, devname);
4023 dol->dol_Name = (BSTR) MKBADDR(devname);
4025 dol = nch->nch_VolEntry;
4026 dol->dol_Next = 0;
4027 dol->dol_Type = DLT_VOLUME;
4028 dol->dol_Task = nch->nch_DOSMsgPort;
4029 dol->dol_Lock = 0;
4030 DateStamp(&dol->dol_misc.dol_volume.dol_VolumeDate);
4031 dol->dol_misc.dol_volume.dol_LockList = 0;
4032 dol->dol_misc.dol_volume.dol_DiskType = ID_DOS_DISK;
4033 devname = (STRPTR) (dol + 1);
4034 c2bstr(nch->nch_RootObject.poi_Name, devname);
4035 dol->dol_Name = (BSTR) MKBADDR(devname);
4037 KPRINTF(10, ("Attempt adding DOSList...\n"));
4038 if(AddDosEntry(nch->nch_DevEntry))
4040 KPRINTF(5, ("Added Device successful!\n"));
4041 nch->nch_ResFlags |= PTPF_DEVNODE;
4042 } else {
4043 KPRINTF(20, ("Could not add Device DOSList\n"));
4046 if(AttemptLockDosList(LDF_DEVICES|LDF_WRITE))
4048 if(AddDosEntry(nch->nch_VolEntry))
4050 KPRINTF(5, ("Added Volume!\n"));
4051 nch->nch_ResFlags |= PTPF_VOLNODE;
4052 } else {
4053 KPRINTF(20, ("Could not add Volume DOSList\n"));
4055 UnLockDosList(LDF_DEVICES|LDF_WRITE);
4059 //psdSendPipe(nch->nch_EPIntPipe, eventbuf, 20);
4062 sigs = Wait(sigmask);
4063 if(sigs & SIGBREAKF_CTRL_C)
4065 nch->nch_ShallExit = TRUE;
4068 nHandleDOSPackets(nch);
4070 if(nch->nch_ShallExit)
4072 if(!nch->nch_VolEntry->dol_misc.dol_volume.dol_LockList)
4074 nch->nch_ResFlags &= ~PTPF_LOCKS;
4075 } else {
4076 struct FileLock *fl = (struct FileLock *) (&nch->nch_VolEntry->dol_misc.dol_volume.dol_LockList);
4077 KPRINTF(20, ("Still locks there %08lx: %08lx.\n", fl, fl->fl_Link));
4078 if(reportlocks)
4080 reportlocks = FALSE;
4081 psdAddErrorMsg(RETURN_ERROR, (STRPTR) libname, "Cannot exit PTP session, there are still pending %s!", (STRPTR) "locks");
4083 while((fl = (struct FileLock *) BADDR(fl->fl_Link)))
4085 KPRINTF(20, ("Locked on %08lx '%s'\n", fl, ((struct PTPObjectInfo *) fl->fl_Key)->poi_Name));
4086 psdAddErrorMsg(RETURN_WARN, (STRPTR) libname,
4087 "Pending lock on '%s'",
4088 ((struct PTPObjectInfo *) fl->fl_Key)->poi_Name);
4092 nch->nch_ResFlags |= PTPF_LOCKS;
4094 if(IsListEmpty(&nch->nch_FHs))
4096 nch->nch_ResFlags &= ~PTPF_FHS;
4097 } else {
4098 KPRINTF(10, ("Still filehandles there.\n"));
4099 if(reportfhs)
4101 reportfhs = FALSE;
4102 psdAddErrorMsg(RETURN_ERROR, (STRPTR) libname, "Cannot exit PTP session, there are still pending %s!", (STRPTR) "filehandles");
4104 nch->nch_ResFlags |= PTPF_FHS;
4106 if(nch->nch_ResFlags & (PTPF_DEVNODE|PTPF_VOLNODE))
4108 KPRINTF(10, ("Attempting removal of DOS Entry!\n"));
4109 if(AttemptLockDosList(LDF_DEVICES|LDF_WRITE))
4111 if(nch->nch_ResFlags & PTPF_VOLNODE)
4113 if(RemDosEntry(nch->nch_VolEntry))
4115 KPRINTF(5, ("DOS Volume Entry removed!\n"));
4116 nch->nch_ResFlags &= ~PTPF_VOLNODE;
4119 if(nch->nch_ResFlags & PTPF_DEVNODE)
4121 if(RemDosEntry(nch->nch_DevEntry))
4123 KPRINTF(5, ("DOS Device Entry removed!\n"));
4124 nch->nch_ResFlags &= ~PTPF_DEVNODE;
4127 UnLockDosList(LDF_DEVICES|LDF_WRITE);
4132 /*while((pp = (struct PsdPipe *) GetMsg(nch->nch_TaskMsgPort)))
4134 if(pp == nch->nch_EPIntPipe)
4136 pktlen = psdGetPipeActual(pp);
4137 if(!(ioerr = psdGetPipeError(pp)))
4139 KPRINTF(1, ("Int Packet returned %ld bytes!\n", pktlen));
4140 } else {
4141 KPRINTF(1, ("Int Pipe failed %ld\n", ioerr));
4142 psdDelayMS(20);
4144 if(!nch->nch_ShallExit)
4146 psdSendPipe(nch->nch_EPIntPipe, eventbuf, 20);
4148 break;
4151 } while(nch->nch_ResFlags || (!nch->nch_ShallExit));
4153 nPTPCloseSession(nch);
4155 KPRINTF(20, ("Going down the river!\n"));
4156 /*psdAbortPipe(nch->nch_EPIntPipe);
4157 psdWaitPipe(nch->nch_EPIntPipe);*/
4158 nFreePTP(nch);
4161 AROS_USERFUNC_EXIT
4163 /* \\\ */
4165 /* /// "nAllocPTP()" */
4166 struct NepClassPTP * nAllocPTP(void)
4168 struct NepPTPBase *nh;
4169 struct Task *thistask;
4170 struct NepClassPTP *nch;
4171 struct PTPObjectInfo *poi;
4172 UWORD cnt;
4174 thistask = FindTask(NULL);
4176 nch = thistask->tc_UserData;
4177 nh = nch->nch_ClsBase;
4178 if(thistask->tc_Node.ln_Type != NT_PROCESS)
4180 KPRINTF(10, ("Can't run as task!\n"));
4181 return(NULL);
4185 if(!(nch->nch_Base = OpenLibrary("poseidon.library", 4)))
4187 Alert(AG_OpenLib);
4188 break;
4190 if(!(nch->nch_DOSBase = OpenLibrary("dos.library", 36)))
4192 Alert(AG_OpenLib|AO_DOSLib);
4193 break;
4195 nch->nch_MemPool = CreatePool(MEMF_CLEAR|MEMF_PUBLIC, 16384, 128);
4196 if(!nch->nch_MemPool)
4198 break;
4200 psdGetAttrs(PGA_INTERFACE, nch->nch_Interface,
4201 IFA_Config, &nch->nch_Config,
4202 IFA_InterfaceNum, &nch->nch_IfNum,
4203 TAG_END);
4204 psdGetAttrs(PGA_CONFIG, nch->nch_Config,
4205 CA_Device, &nch->nch_Device,
4206 TAG_END);
4208 nch->nch_EPIn = psdFindEndpoint(nch->nch_Interface, NULL,
4209 EA_IsIn, TRUE,
4210 EA_TransferType, USEAF_BULK,
4211 TAG_END);
4212 nch->nch_EPOut = psdFindEndpoint(nch->nch_Interface, NULL,
4213 EA_IsIn, FALSE,
4214 EA_TransferType, USEAF_BULK,
4215 TAG_END);
4216 nch->nch_EPInt = psdFindEndpoint(nch->nch_Interface, NULL,
4217 EA_IsIn, TRUE,
4218 EA_TransferType, USEAF_INTERRUPT,
4219 TAG_END);
4221 if(!(nch->nch_EPIn && nch->nch_EPOut))
4222 //if(!(nch->nch_EPIn && nch->nch_EPOut && nch->nch_EPInt))
4224 KPRINTF(1, ("Ooops!?! No Endpoints defined?\n"));
4225 break;
4227 psdGetAttrs(PGA_ENDPOINT, nch->nch_EPIn,
4228 EA_MaxPktSize, &nch->nch_EPInPktSize,
4229 TAG_END);
4231 // init root
4232 poi = &nch->nch_RootObject;
4233 KPRINTF(1, ("Root ObjectInfo %08lx\n", poi));
4234 NewList((struct List *) &poi->poi_Children);
4235 poi->poi_Parent = NULL;
4236 poi->poi_Flags = PTPF_NOPURGE|PTPF_FETCHED;
4237 poi->poi_Handle = 0xffffffff; // as root
4238 poi->poi_StorageID = 0xffffffff;
4239 poi->poi_ObjectFmt = POF_ASSOCIATION; // directory
4240 poi->poi_ProtFlags = FIBF_READ;
4241 poi->poi_ParentHandle = 0; // no parent
4242 poi->poi_Name = NULL;
4243 poi->poi_Keywords = NULL;
4245 // init charmap
4246 for(cnt = 0; cnt < 256; cnt++)
4248 nch->nch_LowCharMap[cnt] = ToLower((ULONG) cnt);
4251 if((nch->nch_DevEntry = nAllocVec(nch, sizeof(struct DosList) + 32)))
4253 if((nch->nch_VolEntry = nAllocVec(nch, sizeof(struct DosList) + 32)))
4255 nch->nch_DOSMsgPort = &((struct Process *) thistask)->pr_MsgPort;
4256 if((nch->nch_TaskMsgPort = CreateMsgPort()))
4258 if((nch->nch_EP0Pipe = psdAllocPipe(nch->nch_Device, nch->nch_TaskMsgPort, NULL)))
4260 if((nch->nch_EPInPipe = psdAllocPipe(nch->nch_Device, nch->nch_TaskMsgPort, nch->nch_EPIn)))
4262 if((nch->nch_EPOutPipe = psdAllocPipe(nch->nch_Device, nch->nch_TaskMsgPort, nch->nch_EPOut)))
4264 //if((nch->nch_EPIntPipe = psdAllocPipe(nch->nch_Device, nch->nch_TaskMsgPort, nch->nch_EPInt)))
4266 psdSetAttrs(PGA_PIPE, nch->nch_EPInPipe,
4267 PPA_AllowRuntPackets, TRUE,
4268 PPA_NakTimeout, TRUE,
4269 PPA_NakTimeoutTime, 5000,
4270 TAG_END);
4271 psdSetAttrs(PGA_PIPE, nch->nch_EPOutPipe,
4272 PPA_NoZeroPktTerm, FALSE,
4273 PPA_NakTimeout, TRUE,
4274 PPA_NakTimeoutTime, 5000,
4275 TAG_END);
4276 nch->nch_Task = thistask;
4277 return(nch);
4279 //psdFreePipe(nch->nch_EPOutPipe);
4281 psdFreePipe(nch->nch_EPInPipe);
4283 psdFreePipe(nch->nch_EP0Pipe);
4285 DeleteMsgPort(nch->nch_TaskMsgPort);
4287 nFreeVec(nch, nch->nch_VolEntry);
4289 nFreeVec(nch, nch->nch_DevEntry);
4291 DeletePool(nch->nch_MemPool);
4292 } while(FALSE);
4293 CloseLibrary(nch->nch_DOSBase);
4294 nch->nch_DOSBase = NULL;
4295 CloseLibrary(nch->nch_Base);
4296 Forbid();
4297 nch->nch_Task = NULL;
4298 if(nch->nch_ReadySigTask)
4300 Signal(nch->nch_ReadySigTask, 1L<<nch->nch_ReadySignal);
4302 return(NULL);
4304 /* \\\ */
4306 /* /// "nFreePTP()" */
4307 void nFreePTP(struct NepClassPTP *nch)
4309 struct PTPStorageInfo *psi;
4310 psi = (struct PTPStorageInfo *) nch->nch_Storages.lh_Head;
4311 while(psi->psi_Node.ln_Succ)
4313 Remove(&psi->psi_Node);
4314 nPTPFreeStorageInfo(nch, psi);
4315 psi = (struct PTPStorageInfo *) nch->nch_Storages.lh_Head;
4317 nch->nch_LastObject = NULL; // Invalidate last object
4318 nFreeVec(nch, nch->nch_LastBuffer);
4319 nch->nch_LastBuffer = NULL;
4321 psdFreePipe(nch->nch_EPInPipe);
4322 psdFreePipe(nch->nch_EPOutPipe);
4323 psdFreePipe(nch->nch_EPIntPipe);
4324 psdFreePipe(nch->nch_EP0Pipe);
4325 DeleteMsgPort(nch->nch_TaskMsgPort);
4326 nFreeVec(nch, nch->nch_VolEntry);
4327 nFreeVec(nch, nch->nch_DevEntry);
4328 DeletePool(nch->nch_MemPool);
4329 CloseLibrary(nch->nch_DOSBase);
4330 nch->nch_DOSBase = NULL;
4331 CloseLibrary(nch->nch_Base);
4332 Forbid();
4333 nch->nch_Task = NULL;
4334 if(nch->nch_ReadySigTask)
4336 Signal(nch->nch_ReadySigTask, 1L<<nch->nch_ReadySignal);
4339 /* \\\ */
4341 /**************************************************************************/
4343 /* /// "nGUITask()" */
4344 AROS_UFH0(void, nGUITask)
4346 AROS_USERFUNC_INIT
4348 struct Task *thistask;
4349 struct NepPTPBase *nh;
4350 struct NepClassPTP *nch;
4351 APTR pic;
4353 thistask = FindTask(NULL);
4354 #undef ps
4355 #define ps nch->nch_PsdBase
4356 #undef IntuitionBase
4357 #define IntuitionBase nch->nch_IntBase
4358 #undef MUIMasterBase
4359 #define MUIMasterBase nch->nch_MUIBase
4360 #undef DOSBase
4361 #define DOSBase nch->nch_DOSBase
4363 nch = thistask->tc_UserData;
4364 nh = nch->nch_ClsBase;
4366 ++nh->nh_Library.lib_OpenCnt;
4367 if(!(MUIMasterBase = OpenLibrary(MUIMASTER_NAME, MUIMASTER_VMIN)))
4369 KPRINTF(10, ("Couldn't open muimaster.library.\n"));
4370 nGUITaskCleanup(nch);
4371 return;
4374 if(!(IntuitionBase = OpenLibrary("intuition.library", 39)))
4376 KPRINTF(10, ("Couldn't open intuition.library.\n"));
4377 nGUITaskCleanup(nch);
4378 return;
4380 if(!(ps = OpenLibrary("poseidon.library", 4)))
4382 KPRINTF(10, ("Couldn't open poseidon.library.\n"));
4383 nGUITaskCleanup(nch);
4384 return;
4387 nch->nch_App = ApplicationObject,
4388 MUIA_Application_Title , (IPTR)libname,
4389 MUIA_Application_Version , (IPTR)VERSION_STRING,
4390 MUIA_Application_Copyright , (IPTR)"©2008-2009 Chris Hodges",
4391 MUIA_Application_Author , (IPTR)"Chris Hodges <chrisly@platon42.de>",
4392 MUIA_Application_Description, (IPTR)"Settings for the ptp.class",
4393 MUIA_Application_Base , (IPTR)"PTP",
4394 MUIA_Application_HelpFile , (IPTR)"HELP:Poseidon.guide",
4395 MUIA_Application_Menustrip , (IPTR)MenustripObject,
4396 Child, (IPTR)MenuObjectT((IPTR)"Project"),
4397 Child, (IPTR)(nch->nch_AboutMI = MenuitemObject,
4398 MUIA_Menuitem_Title, (IPTR)"About...",
4399 MUIA_Menuitem_Shortcut, (IPTR)"?",
4400 End),
4401 End,
4402 Child, (IPTR)MenuObjectT((IPTR)"Settings"),
4403 Child, (IPTR)(nch->nch_UseMI = MenuitemObject,
4404 MUIA_Menuitem_Title, (IPTR)"Save",
4405 MUIA_Menuitem_Shortcut, (IPTR)"S",
4406 End),
4407 Child, (IPTR)(nch->nch_SetDefaultMI = MenuitemObject,
4408 MUIA_Menuitem_Title, (IPTR)"Save as Default",
4409 MUIA_Menuitem_Shortcut, (IPTR)"D",
4410 End),
4411 Child, (IPTR)MenuitemObject,
4412 MUIA_Menuitem_Title, (IPTR)NM_BARLABEL,
4413 End,
4414 Child, (IPTR)(nch->nch_MUIPrefsMI = MenuitemObject,
4415 MUIA_Menuitem_Title, (IPTR)"MUI Settings",
4416 MUIA_Menuitem_Shortcut, (IPTR)"M",
4417 End),
4418 End,
4419 End,
4421 SubWindow, (IPTR)(nch->nch_MainWindow = WindowObject,
4422 MUIA_Window_ID , MAKE_ID('M','A','I','N'),
4423 MUIA_Window_Title, (IPTR)libname,
4424 MUIA_HelpNode, (IPTR)libname,
4426 WindowContents, (IPTR)VGroup,
4427 Child, (IPTR)VGroup, GroupFrameT((IPTR)"PTP Settings"),
4428 Child, (IPTR)HGroup,
4429 Child, (IPTR)Label((IPTR) "DOS Device Name:"),
4430 Child, (IPTR)(nch->nch_DOSNameObj = StringObject,
4431 StringFrame,
4432 MUIA_CycleChain, 1,
4433 MUIA_String_AdvanceOnCR, TRUE,
4434 MUIA_String_Contents, (IPTR)nch->nch_CDC->cdc_DOSName,
4435 MUIA_String_Reject, (IPTR)"/ :?#*",
4436 MUIA_String_MaxLen, 31,
4437 End),
4438 End,
4439 Child, (IPTR)ColGroup(2),
4440 Child, (IPTR)Label((IPTR) "Always fully load and cache objects:"),
4441 Child, (IPTR)(nch->nch_NoPartObjObj = ImageObject, ImageButtonFrame,
4442 MUIA_Background, MUII_ButtonBack,
4443 MUIA_CycleChain, 1,
4444 MUIA_InputMode, MUIV_InputMode_Toggle,
4445 MUIA_Image_Spec, MUII_CheckMark,
4446 MUIA_Image_FreeVert, TRUE,
4447 MUIA_Selected, nch->nch_CDC->cdc_NoPartObj,
4448 MUIA_ShowSelState, FALSE,
4449 End),
4450 Child, (IPTR)Label((IPTR) "Try to detect MTP devices:"),
4451 Child, (IPTR)(nch->nch_EnableMTPObj = ImageObject, ImageButtonFrame,
4452 MUIA_Disabled, nch->nch_Interface ? TRUE : FALSE,
4453 MUIA_Background, MUII_ButtonBack,
4454 MUIA_CycleChain, 1,
4455 MUIA_InputMode, MUIV_InputMode_Toggle,
4456 MUIA_Image_Spec, MUII_CheckMark,
4457 MUIA_Image_FreeVert, TRUE,
4458 MUIA_Selected, nch->nch_CDC->cdc_EnableMTP,
4459 MUIA_ShowSelState, FALSE,
4460 End),
4461 End,
4462 End,
4463 Child, (IPTR)VSpace(0),
4464 Child, (IPTR)HGroup,
4465 MUIA_Group_SameWidth, TRUE,
4466 Child, (IPTR)(nch->nch_UseObj = TextObject, ButtonFrame,
4467 MUIA_ShowMe, (IPTR)nch->nch_Interface,
4468 MUIA_Background, MUII_ButtonBack,
4469 MUIA_CycleChain, 1,
4470 MUIA_InputMode, MUIV_InputMode_RelVerify,
4471 MUIA_Text_Contents, (IPTR)"\33c Save ",
4472 End),
4473 Child, (IPTR)(nch->nch_SetDefaultObj = TextObject, ButtonFrame,
4474 MUIA_Background, MUII_ButtonBack,
4475 MUIA_CycleChain, 1,
4476 MUIA_InputMode, MUIV_InputMode_RelVerify,
4477 MUIA_Text_Contents, (IPTR)(nch->nch_Interface ? "\33c Save as Default " : "\33c Save Defaults "),
4478 End),
4479 Child, (IPTR)(nch->nch_CloseObj = TextObject, ButtonFrame,
4480 MUIA_Background, MUII_ButtonBack,
4481 MUIA_CycleChain, 1,
4482 MUIA_InputMode, MUIV_InputMode_RelVerify,
4483 MUIA_Text_Contents, (IPTR)"\33c Use ",
4484 End),
4485 End,
4486 End,
4487 End),
4488 End;
4490 if(!nch->nch_App)
4492 KPRINTF(10, ("Couldn't create application\n"));
4493 nGUITaskCleanup(nch);
4494 return;
4497 DoMethod(nch->nch_MainWindow, MUIM_Notify, MUIA_Window_CloseRequest, TRUE,
4498 nch->nch_App, 2, MUIM_Application_ReturnID, MUIV_Application_ReturnID_Quit);
4499 DoMethod(nch->nch_UseObj, MUIM_Notify, MUIA_Pressed, FALSE,
4500 nch->nch_App, 2, MUIM_Application_ReturnID, ID_STORE_CONFIG);
4501 DoMethod(nch->nch_SetDefaultObj, MUIM_Notify, MUIA_Pressed, FALSE,
4502 nch->nch_App, 2, MUIM_Application_ReturnID, ID_DEF_CONFIG);
4503 DoMethod(nch->nch_CloseObj, MUIM_Notify, MUIA_Pressed, FALSE,
4504 nch->nch_App, 2, MUIM_Application_ReturnID, MUIV_Application_ReturnID_Quit);
4506 DoMethod(nch->nch_AboutMI, MUIM_Notify, MUIA_Menuitem_Trigger, MUIV_EveryTime,
4507 nch->nch_App, 2, MUIM_Application_ReturnID, ID_ABOUT);
4508 DoMethod(nch->nch_UseMI, MUIM_Notify, MUIA_Menuitem_Trigger, MUIV_EveryTime,
4509 nch->nch_App, 2, MUIM_Application_ReturnID, ID_STORE_CONFIG);
4510 DoMethod(nch->nch_SetDefaultMI, MUIM_Notify, MUIA_Menuitem_Trigger, MUIV_EveryTime,
4511 nch->nch_App, 2, MUIM_Application_ReturnID, ID_DEF_CONFIG);
4512 DoMethod(nch->nch_MUIPrefsMI, MUIM_Notify, MUIA_Menuitem_Trigger, MUIV_EveryTime,
4513 nch->nch_App, 2, MUIM_Application_OpenConfigWindow, 0);
4515 IPTR isopen = 0;
4516 IPTR iconify = 0;
4517 ULONG sigs;
4518 ULONG sigmask;
4519 LONG retid;
4521 get(nch->nch_App, MUIA_Application_Iconified, &iconify);
4522 set(nch->nch_MainWindow, MUIA_Window_Open, TRUE);
4523 get(nch->nch_MainWindow, MUIA_Window_Open, &isopen);
4524 if(!(isopen || iconify))
4526 nGUITaskCleanup(nch);
4527 return;
4529 sigmask = 0;
4532 retid = DoMethod(nch->nch_App, MUIM_Application_NewInput, &sigs);
4533 switch(retid)
4535 case ID_DEF_CONFIG:
4536 case ID_STORE_CONFIG:
4537 case MUIV_Application_ReturnID_Quit:
4539 STRPTR tmpstr;
4541 get(nch->nch_EnableMTPObj, MUIA_Selected, &nch->nch_CDC->cdc_EnableMTP);
4542 get(nch->nch_NoPartObjObj, MUIA_Selected, &nch->nch_CDC->cdc_NoPartObj);
4543 tmpstr = "";
4544 get(nch->nch_DOSNameObj, MUIA_String_Contents, &tmpstr);
4545 strncpy(nch->nch_CDC->cdc_DOSName, tmpstr, 31);
4547 if(retid == ID_DEF_CONFIG)
4549 pic = psdGetClsCfg(libname);
4550 if(!pic)
4552 psdSetClsCfg(libname, NULL);
4553 pic = psdGetClsCfg(libname);
4555 if(pic)
4557 if(psdAddCfgEntry(pic, nch->nch_CDC))
4559 psdSaveCfgToDisk(NULL, FALSE);
4563 if(nch->nch_Interface)
4565 pic = psdGetUsbDevCfg(libname, nch->nch_DevIDString, nch->nch_IfIDString);
4566 if(!pic)
4568 psdSetUsbDevCfg(libname, nch->nch_DevIDString, nch->nch_IfIDString, NULL);
4569 pic = psdGetUsbDevCfg(libname, nch->nch_DevIDString, nch->nch_IfIDString);
4571 if(pic)
4573 if(psdAddCfgEntry(pic, nch->nch_CDC))
4575 if(retid != MUIV_Application_ReturnID_Quit)
4577 psdSaveCfgToDisk(NULL, FALSE);
4579 retid = MUIV_Application_ReturnID_Quit;
4582 } else {
4583 retid = MUIV_Application_ReturnID_Quit;
4585 break;
4588 case ID_ABOUT:
4589 MUI_RequestA(nch->nch_App, nch->nch_MainWindow, 0, NULL, "Moo!", VERSION_STRING, NULL);
4590 break;
4592 if(retid == MUIV_Application_ReturnID_Quit)
4594 break;
4596 if(sigs)
4598 sigs = Wait(sigs | sigmask | SIGBREAKF_CTRL_C);
4599 if(sigs & SIGBREAKF_CTRL_C)
4601 break;
4604 } while(TRUE);
4605 set(nch->nch_MainWindow, MUIA_Window_Open, FALSE);
4607 nGUITaskCleanup(nch);
4609 AROS_USERFUNC_EXIT
4611 /* \\\ */
4613 /* /// "nGUITaskCleanup()" */
4614 void nGUITaskCleanup(struct NepClassPTP *nch)
4616 if(nch->nch_App)
4618 MUI_DisposeObject(nch->nch_App);
4619 nch->nch_App = NULL;
4621 if(MUIMasterBase)
4623 CloseLibrary(MUIMasterBase);
4624 MUIMasterBase = NULL;
4626 if(IntuitionBase)
4628 CloseLibrary(IntuitionBase);
4629 IntuitionBase = NULL;
4631 if(ps)
4633 CloseLibrary(ps);
4634 ps = NULL;
4636 Forbid();
4637 nch->nch_GUIBinding = NULL;
4638 nch->nch_GUITask = NULL;
4639 if(nch->nch_ReadySigTask)
4641 Signal(nch->nch_ReadySigTask, 1L<<nch->nch_ReadySignal);
4643 --nch->nch_ClsBase->nh_Library.lib_OpenCnt;
4645 /* \\\ */