2 *----------------------------------------------------------------------------
3 * ptp class for poseidon
4 *----------------------------------------------------------------------------
5 * By Chris Hodges <chrisly@platon42.de>
10 #include "ptp.class.h"
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
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
);
41 CloseLibrary(UtilityBase
);
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
));
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
);
68 ADD2INITLIB(libInit
, 0)
69 ADD2OPENLIB(libOpen
, 0)
70 ADD2EXPUNGELIB(libExpunge
, 0)
74 * ***********************************************************************
75 * * Library functions *
76 * ***********************************************************************
79 /* /// "usbAttemptInterfaceBinding()" */
80 struct NepClassPTP
* usbAttemptInterfaceBinding(struct NepPTPBase
*nh
, struct PsdInterface
*pif
)
91 BOOL checkformtp
= FALSE
;
94 KPRINTF(1, ("nepPTPAttemptInterfaceBinding(%08lx)\n", pif
));
95 if((ps
= OpenLibrary("poseidon.library", 4)))
97 psdGetAttrs(PGA_INTERFACE
, pif
,
99 IFA_SubClass
, &ifsubclass
,
100 IFA_Protocol
, &ifproto
,
104 if((ifclass
== STILLIMG_CLASSCODE
) && (ifsubclass
== 0x01) && (ifproto
== 0x01))
108 if(nh
->nh_DummyNCH
.nch_CDC
->cdc_EnableMTP
)
110 psdGetAttrs(PGA_CONFIG
, pc
,
113 psdGetAttrs(PGA_DEVICE
, pd
,
115 DA_SubClass
, &subclass
,
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
));
127 checkformtp
= psdFindEndpoint(pif
, NULL
,
129 EA_TransferType
, USEAF_BULK
,
131 psdFindEndpoint(pif
, NULL
,
133 EA_TransferType
, USEAF_BULK
,
135 psdFindEndpoint(pif, NULL,
137 EA_TransferType, USEAF_INTERRUPT,
145 if((mp
= CreateMsgPort()))
147 if((pp
= psdAllocPipe(pd
, mp
, NULL
)))
149 psdSetAttrs(PGA_PIPE
, pp
,
150 PPA_NakTimeout
, TRUE
,
151 PPA_NakTimeoutTime
, 500,
153 psdAddErrorMsg(RETURN_OK
, (STRPTR
) libname
, "This might be an MTP device, we will look in detail.");
154 idstr
= psdGetStringDescriptor(pp
, 0xee);
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.");
174 return(usbForceInterfaceBinding(nh
, pif
));
181 /* /// "usbForceInterfaceBinding()" */
182 struct NepClassPTP
* usbForceInterfaceBinding(struct NepPTPBase
*nh
, struct PsdInterface
*pif
)
185 struct NepClassPTP
*nch
;
186 struct PsdConfig
*pc
;
187 struct PsdDevice
*pd
;
196 struct Task
*tmptask
;
198 KPRINTF(1, ("nepPTPForceInterfaceBinding(%08lx)\n", pif
));
199 if((ps
= OpenLibrary("poseidon.library", 4)))
201 psdGetAttrs(PGA_INTERFACE
, pif
,
203 IFA_IDString
, &ifidstr
,
204 IFA_InterfaceNum
, &ifnum
,
205 IFA_Protocol
, &ifproto
,
207 psdGetAttrs(PGA_CONFIG
, pc
,
210 psdGetAttrs(PGA_DEVICE
, pd
,
211 DA_ProductName
, &devname
,
213 DA_ProductID
, &prodid
,
214 DA_IDString
, &devidstr
,
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
);
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
);
245 nch
->nch_ReadySigTask
= NULL
;
246 //FreeSignal(nch->nch_ReadySignal);
247 psdAddErrorMsg(RETURN_OK
, (STRPTR
) libname
,
248 "Hold still for images from for '%s'!",
252 AddTail(&nh
->nh_Bindings
, &nch
->nch_Node
);
258 nch
->nch_ReadySigTask
= NULL
;
259 //FreeSignal(nch->nch_ReadySignal);
260 FreeVec(nch
->nch_CDC
);
272 /* /// "usbReleaseInterfaceBinding()" */
273 void usbReleaseInterfaceBinding(struct NepPTPBase
*nh
, struct NepClassPTP
*nch
)
276 struct PsdConfig
*pc
;
277 struct PsdDevice
*pd
;
280 KPRINTF(1, ("nepPTPReleaseInterfaceBinding(%08lx)\n", nch
));
281 if((ps
= OpenLibrary("poseidon.library", 4)))
284 nch
->nch_ReadySignal
= SIGB_SINGLE
;
285 nch
->nch_ReadySigTask
= FindTask(NULL
);
288 Signal(nch
->nch_GUITask
, SIGBREAKF_CTRL_C
);
291 while(nch
->nch_GUITask
)
293 Wait(1L<<nch
->nch_ReadySignal
);
299 Signal(nch
->nch_Task
, SIGBREAKF_CTRL_C
);
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!",
314 Remove(&nch
->nch_Node
);
316 FreeVec(nch
->nch_CDC
);
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
)
335 KPRINTF(1, ("nepPTPGetAttrsA(%ld, %08lx, %08lx)\n", type
, usbstruct
, tags
));
339 if((ti
= FindTagItem(UCCA_Priority
, tags
)))
341 *((SIPTR
*) ti
->ti_Data
) = -100;
344 if((ti
= FindTagItem(UCCA_Description
, tags
)))
346 *((STRPTR
*) ti
->ti_Data
) = "Support for DigiCams and MTP via PictureTransferProtocol (PTP)";
349 if((ti
= FindTagItem(UCCA_HasClassCfgGUI
, tags
)))
351 *((IPTR
*) ti
->ti_Data
) = TRUE
;
354 if((ti
= FindTagItem(UCCA_HasBindingCfgGUI
, tags
)))
356 *((IPTR
*) ti
->ti_Data
) = TRUE
;
359 if((ti
= FindTagItem(UCCA_AfterDOSRestart
, tags
)))
361 *((IPTR
*) ti
->ti_Data
) = FALSE
;
364 if((ti
= FindTagItem(UCCA_UsingDefaultCfg
, tags
)))
366 *((IPTR
*) ti
->ti_Data
) = nh
->nh_DummyNCH
.nch_UsingDefaultCfg
;
372 if((ti
= FindTagItem(UCBA_UsingDefaultCfg
, tags
)))
374 *((IPTR
*) ti
->ti_Data
) = ((struct NepClassPTP
*) usbstruct
)->nch_UsingDefaultCfg
;
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
)
397 /* /// "usbDoMethodA()" */
398 AROS_LH2(IPTR
, usbDoMethodA
,
399 AROS_LHA(ULONG
, methodid
, D0
),
400 AROS_LHA(IPTR
*, methoddata
, A1
),
401 LIBBASETYPEPTR
, nh
, 7, nep
)
405 struct NepClassPTP
*nch
;
407 KPRINTF(1, ("Do Method %ld\n", 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]);
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
);
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
;
446 /* /// "nLoadClassConfig()" */
447 BOOL
nLoadClassConfig(struct NepPTPBase
*nh
)
449 struct NepClassPTP
*nch
= &nh
->nh_DummyNCH
;
451 struct ClsDevCfg
*cdc
;
452 struct PsdIFFContext
*pic
;
454 KPRINTF(1, ("Loading Class Config...\n"));
459 if(!(ps
= OpenLibrary("poseidon.library", 4)))
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
);
476 cdc
= psdGetCfgChunk(pic
, AROS_LONG2BE(nch
->nch_CDC
->cdc_ChunkID
));
479 CopyMem(((UBYTE
*) cdc
) + 8, ((UBYTE
*) nch
->nch_CDC
) + 8, min(AROS_LONG2BE(cdc
->cdc_Length
), AROS_LONG2BE(nch
->nch_CDC
->cdc_Length
)));
481 nch
->nch_UsingDefaultCfg
= FALSE
;
490 /* /// "nLoadBindingConfig()" */
491 BOOL
nLoadBindingConfig(struct NepClassPTP
*nch
)
493 struct NepPTPBase
*nh
= nch
->nch_ClsBase
;
495 struct ClsDevCfg
*cdc
;
496 struct PsdIFFContext
*pic
;
498 KPRINTF(1, ("Loading Binding Config...\n"));
503 nLoadClassConfig(nh
);
504 *nch
->nch_CDC
= *nh
->nh_DummyNCH
.nch_CDC
;
505 nch
->nch_UsingDefaultCfg
= TRUE
;
507 if(!(ps
= OpenLibrary("poseidon.library", 4)))
514 pic
= psdGetUsbDevCfg(libname
, nch
->nch_DevIDString
, nch
->nch_IfIDString
);
517 cdc
= psdGetCfgChunk(pic
, AROS_LONG2BE(nch
->nch_CDC
->cdc_ChunkID
));
520 CopyMem(((UBYTE
*) cdc
) + 8, ((UBYTE
*) nch
->nch_CDC
) + 8, min(AROS_LONG2BE(cdc
->cdc_Length
), AROS_LONG2BE(nch
->nch_CDC
->cdc_Length
)));
522 nch
->nch_UsingDefaultCfg
= FALSE
;
531 /* /// "nOpenBindingCfgWindow()" */
532 LONG
nOpenBindingCfgWindow(struct NepPTPBase
*nh
, struct NepClassPTP
*nch
)
535 KPRINTF(1, ("Opening GUI...\n"));
536 if(!(ps
= OpenLibrary("poseidon.library", 4)))
541 if(!nch
->nch_GUITask
)
543 if((nch
->nch_GUITask
= psdSpawnSubTask(MOD_NAME_STRING
" GUI", nGUITask
, nch
)))
556 /**************************************************************************/
559 #define ps nch->nch_Base
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)\
570 STRPTR cp = (STRPTR) (cstr);\
571 STRPTR bp = (STRPTR) (bstr);\
580 /* /// "nAllocVec()" */
581 APTR
nAllocVec(struct NepClassPTP
*nch
, ULONG size
)
585 mem
= (ULONG
*) AllocPooled(nch
->nch_MemPool
, size
);
595 /* /// "nFreeVec()" */
596 void nFreeVec(struct NepClassPTP
*nch
, APTR mem
)
598 ULONG
*memptr
= (ULONG
*) mem
;
607 KPRINTF(20, ("illegal size %ld for block %08lx\n", size
, memptr
));
609 FreePooled(nch
->nch_MemPool
, memptr
, size
);
613 /* /// "nPsdStrToNStr()" */
614 STRPTR
nPsdStrToNStr(struct NepClassPTP
*nch
, STRPTR oldstr
)
617 STRPTR strptr
= oldstr
;
628 newstr
= nAllocVec(nch
, len
);
633 while((*tarptr
++ = *strptr
++));
640 /* /// "nSendPTPCmd()" */
641 LONG
nSendPTPCmd(struct NepClassPTP
*nch
, struct PTPOp
*po
)
643 ULONG len
= 4+2+2+4+(po
->po_NumParam
<<2);
645 ULONG cmd
= po
->po_OpCode
;
649 KPRINTF(10, ("Sending Command %04lx (%s) with %ld params\n",
651 nNumToStr(nch
, NTS_OPCODE
, cmd
, "unknown"),
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
);
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
);
683 /* /// "nSendPTPData()" */
684 LONG
nSendPTPData(struct NepClassPTP
*nch
, struct PTPOp
*po
, UBYTE
*data
, ULONG datalen
)
686 ULONG len
= 4+2+2+4+datalen
;
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",
693 nNumToStr(nch
, NTS_OPCODE
, cmd
, "unknown"),
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
,
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
,
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
);
723 ioerr
= psdDoPipe(nch
->nch_EPOutPipe
, &data
[500], datalen
- 500);
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
);
736 /* /// "nGetPTPRsp()" */
737 UBYTE
* nGetPTPRsp(struct NepClassPTP
*nch
, struct PTPResponse
*pr
)
743 struct PTPResponse
*tmppr
= (struct PTPResponse
*) nch
->nch_InBuf
;
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);
758 KPRINTF(10, ("IOerror %ld, actual=%ld\n", ioerr
, psdGetPipeActual(nch
->nch_EPInPipe
)));
764 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) libname
,
765 "Reading Response failed: %s (%ld)!",
766 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
767 pr
->pr_IOErr
= ioerr
;
771 iolen
= psdGetPipeActual(nch
->nch_EPInPipe
);
772 KPRINTF(5, ("Response received %ld\n", iolen
));
773 DB(dumpmem(nch
->nch_InBuf
, iolen
));
776 KPRINTF(20, ("Response %ld too short!\n", iolen
));
777 pr
->pr_IOErr
= UHIOERR_RUNTPACKET
;
780 len
= AROS_LONG2LE(tmppr
->pr_Length
);
781 KPRINTF(10, ("Total response %ld\n", len
));
784 KPRINTF(20, ("Response %ld exceeds %ld length field!\n", iolen
, len
));
785 pr
->pr_IOErr
= UHIOERR_RUNTPACKET
;
789 if((len
< 512) && (iolen
< len
))
791 KPRINTF(20, ("Response %ld shorter than %ld length field!\n", iolen
, len
));
795 KPRINTF(1, ("Assuming that data follows in a separate transfer.\n"));
797 pr
->pr_IOErr
= UHIOERR_RUNTPACKET
;
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
);
820 pr
->pr_IOErr
= UHIOERR_OUTOFMEMORY
;
823 CopyMem(&nch
->nch_InBuf
[12], buf
, iolen
- 12);
829 ioerr
= psdDoPipe(nch
->nch_EPInPipe
, &buf
[iolen
- 12], len
- iolen
);
838 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) libname
,
839 "Reading Data failed: %s (%ld)!",
840 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
841 pr
->pr_IOErr
= ioerr
;
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"));
856 ioerr
= psdDoPipe(nch
->nch_EPInPipe
, nch
->nch_InBuf
, 512);
864 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) libname
,
865 "Reading Response failed: %s (%ld)!",
866 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
867 pr
->pr_IOErr
= ioerr
;
872 iolen
= psdGetPipeActual(nch
->nch_EPInPipe
);
875 KPRINTF(20, ("Response %ld too short!\n", iolen
));
876 pr
->pr_IOErr
= UHIOERR_RUNTPACKET
;
880 len
= AROS_LONG2LE(tmppr
->pr_Length
);
883 KPRINTF(20, ("Response %ld exceeds %ld length field!\n", iolen
, len
));
884 pr
->pr_IOErr
= UHIOERR_RUNTPACKET
;
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
;
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",
914 nNumToStr(nch
, NTS_RESPCODE
, (ULONG
) pr
->pr_RespCode
, "unknown"),
916 if(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
]));
934 /* /// "nGetPTPRspData()" */
935 UBYTE
* nGetPTPRspData(struct NepClassPTP
*nch
, struct PTPResponse
*pr
, UBYTE
*buf
, ULONG buflen
)
942 struct PTPResponse
*tmppr
= (struct PTPResponse
*) nch
->nch_InBuf
;
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);
956 KPRINTF(10, ("IOerror %ld, actual=%ld\n", ioerr
, psdGetPipeActual(nch
->nch_EPInPipe
)));
962 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) libname
,
963 "Reading Response failed: %s (%ld)!",
964 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
965 pr
->pr_IOErr
= ioerr
;
969 iolen
= psdGetPipeActual(nch
->nch_EPInPipe
);
970 KPRINTF(5, ("Response received %ld\n", iolen
));
971 DB(dumpmem(nch
->nch_InBuf
, iolen
));
974 KPRINTF(20, ("Response %ld too short!\n", iolen
));
975 pr
->pr_IOErr
= UHIOERR_RUNTPACKET
;
978 len
= AROS_LONG2LE(tmppr
->pr_Length
);
979 KPRINTF(10, ("Total response %ld\n", len
));
982 KPRINTF(20, ("Response %ld exceeds %ld length field!\n", iolen
, len
));
983 pr
->pr_IOErr
= UHIOERR_RUNTPACKET
;
987 if((len
< 512) && (iolen
< len
))
989 KPRINTF(20, ("Response %ld shorter than %ld length field!\n", iolen
, len
));
992 KPRINTF(20, ("Assuming that data follows in a separate transfer.\n"));
994 pr
->pr_IOErr
= UHIOERR_RUNTPACKET
;
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
);
1023 CopyMem(&nch
->nch_InBuf
[12], buf
, iolen
- 12);
1027 if(buflen
== len
- 12)
1032 ioerr
= psdDoPipe(nch
->nch_EPInPipe
, &buf
[iolen
- 12], len
- iolen
+ 12);
1039 remlen
= buflen
- iolen
+ 12;
1042 ioerr
= psdDoPipe(nch
->nch_EPInPipe
, &buf
[iolen
- 12], remlen
& ~511);
1046 ioerr
= psdDoPipe(nch
->nch_EPInPipe
, nch
->nch_InBuf
, 512);
1049 CopyMem(nch
->nch_EPInPipe
, &buf
[iolen
- 12 + (remlen
& ~511)], remlen
& 511);
1055 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) libname
,
1056 "Reading Data failed: %s (%ld)!",
1057 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
1058 pr
->pr_IOErr
= ioerr
;
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"));
1073 ioerr
= psdDoPipe(nch
->nch_EPInPipe
, nch
->nch_InBuf
, 512);
1081 psdAddErrorMsg(RETURN_ERROR
, (STRPTR
) libname
,
1082 "Reading Response failed: %s (%ld)!",
1083 psdNumToStr(NTS_IOERR
, ioerr
, "unknown"), ioerr
);
1084 pr
->pr_IOErr
= ioerr
;
1088 iolen
= psdGetPipeActual(nch
->nch_EPInPipe
);
1091 KPRINTF(20, ("Response %ld too short!\n", iolen
));
1092 pr
->pr_IOErr
= UHIOERR_RUNTPACKET
;
1095 len
= AROS_LONG2LE(tmppr
->pr_Length
);
1098 KPRINTF(20, ("Response %ld exceeds %ld length field!\n", iolen
, len
));
1099 pr
->pr_IOErr
= UHIOERR_RUNTPACKET
;
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
;
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",
1127 nNumToStr(nch
, NTS_RESPCODE
, (ULONG
) pr
->pr_RespCode
, "unknown"),
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
]));
1147 /* /// "nGetPimaStr()" */
1148 STRPTR
nGetPimaStr(struct NepClassPTP
*nch
, UBYTE
*bufptr
, STRPTR emptystr
)
1150 ULONG len
= *bufptr
++;
1161 res
= nAllocVec(nch
, (ULONG
) strlen(emptystr
) + 1);
1166 strcpy(res
, emptystr
);
1170 res
= nAllocVec(nch
, len
+ 1);
1179 widechar
= *bufptr
++;
1180 widechar
|= (*bufptr
++)<<8;
1185 if((widechar
> 255) || (widechar
< 32))
1189 *strptr
++ = widechar
;
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
;
1212 widechar
= *bufptr
++;
1213 widechar
|= (*bufptr
++)<<8;
1218 if((widechar
> 255) || (widechar
< 32))
1222 if((widechar
== '/') || (widechar
== ':') ||
1223 (widechar
== '*') || (widechar
== '"') ||
1224 (widechar
== '\'') || (widechar
== '>') ||
1225 (widechar
== '<') || (widechar
== '\\'))
1229 *strptr
++ = widechar
;
1238 /* /// "nWritePimaStr()" */
1239 UBYTE
* nWritePimaStr(struct NepClassPTP
*nch
, UBYTE
*bufptr
, STRPTR strptr
)
1242 STRPTR srcptr
= strptr
;
1259 *bufptr
++ = *strptr
++;
1268 /* /// "nCheckPTPError()" */
1269 BOOL
nCheckPTPError(struct NepClassPTP
*nch
, struct PTPOp
*po
, struct PTPResponse
*pr
)
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
);
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
);
1293 /* /// "nConvertArrayULONG()" */
1294 BOOL
nConvertArrayULONG(struct NepClassPTP
*nch
, UBYTE
*buf
, ULONG maxlen
)
1297 ULONG
*tmpptr
= (ULONG
*) buf
;
1302 KPRINTF(20, ("Array crippled!\n", maxlen
));
1308 cnt
|= (*buf
++)<<16;
1309 cnt
|= (*buf
++)<<24;
1314 if((cnt
<<2) > maxlen
)
1316 KPRINTF(20, ("Array exceeds buffer (%ld > %ld)!\n", cnt
, maxlen
>>2));
1325 *tmpptr
++ = AROS_LONG2LE(tmpval
);
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 };
1347 if(*bufptr
< 16) // minimum length required
1353 // parse YYYYMMDDThhmmss
1357 ch
|= (*bufptr
++)<<8;
1358 if((ch
< '0') || (ch
> '9'))
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
);
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
));
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 };
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
);
1452 /* /// "nCalcNameHash()" */
1453 UWORD
nCalcNameHash(struct NepClassPTP
*nch
, STRPTR ptr
)
1455 UWORD hash
= 0x1234;
1460 while(*ptr
&& (*ptr
!= '/') && (*ptr
!= ':'))
1462 hash
^= (hash
<<3)|(hash
>>13);
1464 hash
^= nch
->nch_LowCharMap
[*ptr
++];
1470 /* /// "nPTPGetDeviceInfo()" */
1471 BOOL
nPTPGetDeviceInfo(struct NepClassPTP
*nch
)
1474 struct PTPResponse pr
;
1489 po
.po_OpCode
= POC_GETDEVICEINFO
;
1492 ioerr
= nSendPTPCmd(nch
, &po
);
1495 pr
.pr_TransID
= po
.po_TransID
;
1496 tmpptr
= buf
= nGetPTPRsp(nch
, &pr
);
1497 if(nCheckPTPError(nch
, &po
, &pr
))
1505 tmpptr
+= (*tmpptr
)<<1; // skip VendorExtensionDesc;
1508 cnt
|= (*tmpptr
++)<<8;
1509 cnt
|= (*tmpptr
++)<<16;
1510 cnt
|= (*tmpptr
++)<<24;
1511 KPRINTF(10, ("OpCodes: %ld\n", cnt
));
1512 nch
->nch_DevCaps
= 0;
1516 code
|= (*tmpptr
++)<<8;
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).");
1527 case POC_SENDOBJECTINFO
:
1528 case POC_SENDOBJECT
:
1529 nch
->nch_DevCaps
|= PTPF_SENDOBJ
;
1532 case POC_DELETEOBJECT
:
1533 nch
->nch_DevCaps
|= PTPF_DELETEOBJ
;
1536 case POC_SETOBJECTPROTECTION
:
1537 nch
->nch_DevCaps
|= PTPF_PROTOBJ
;
1540 case POC_MOVEOBJECT
:
1541 nch
->nch_DevCaps
|= PTPF_MOVEOBJ
;
1544 case POC_FORMATSTORE
:
1545 nch
->nch_DevCaps
|= PTPF_FORMAT
;
1549 KPRINTF(1, ("%04lx: %s\n", code
, nNumToStr(nch
, NTS_OPCODE
, code
, "unknown")));
1553 cnt
|= (*tmpptr
++)<<8;
1554 cnt
|= (*tmpptr
++)<<16;
1555 cnt
|= (*tmpptr
++)<<24;
1557 KPRINTF(10, ("EventCodes: %ld\n", cnt
));
1561 code
|= (*tmpptr
++)<<8;
1562 KPRINTF(1, ("%04lx: %s\n", code
, nNumToStr(nch
, NTS_EVENTCODE
, code
, "unknown")));
1570 cnt
|= (*tmpptr
++)<<8;
1571 cnt
|= (*tmpptr
++)<<16;
1572 cnt
|= (*tmpptr
++)<<24;
1574 KPRINTF(10, ("DevicePropCodes: %ld\n", cnt
));
1578 code
|= (*tmpptr
++)<<8;
1579 KPRINTF(1, ("%04lx: %s\n", code
, nNumToStr(nch
, NTS_DEVICEPROPCODE
, code
, "unknown")));
1587 cnt
|= (*tmpptr
++)<<8;
1588 cnt
|= (*tmpptr
++)<<16;
1589 cnt
|= (*tmpptr
++)<<24;
1591 KPRINTF(10, ("CaptureFormats: %ld\n", cnt
));
1595 code
|= (*tmpptr
++)<<8;
1596 KPRINTF(1, ("%04lx: %s\n", code
, nNumToStr(nch
, NTS_OBJECTFMTCODE
, code
, "unknown")));
1604 cnt
|= (*tmpptr
++)<<8;
1605 cnt
|= (*tmpptr
++)<<16;
1606 cnt
|= (*tmpptr
++)<<24;
1608 KPRINTF(10, ("ImageFormats: %ld\n", cnt
));
1612 code
|= (*tmpptr
++)<<8;
1613 KPRINTF(1, ("%04lx: %s\n", code
, nNumToStr(nch
, NTS_OBJECTFMTCODE
, code
, "unknown")));
1620 psdGetAttrs(PGA_DEVICE
, nch
->nch_Device
,
1621 DA_ProductName
, &devname
,
1622 DA_Manufacturer
, &devmanuname
,
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
1637 tarptr
= nch
->nch_VolumeName
;
1651 *tarptr
++ = *srcptr
;
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'.",
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
));
1681 /* /// "nPTPOpenSession()" */
1682 BOOL
nPTPOpenSession(struct NepClassPTP
*nch
)
1685 struct PTPResponse pr
;
1689 nch
->nch_SessionID
= 0;
1690 nch
->nch_TransID
= 0;
1692 po
.po_OpCode
= POC_OPENSESSION
;
1696 ioerr
= nSendPTPCmd(nch
, &po
);
1699 pr
.pr_TransID
= po
.po_TransID
;
1700 buf
= nGetPTPRsp(nch
, &pr
);
1701 if(nCheckPTPError(nch
, &po
, &pr
))
1708 nch
->nch_SessionID
= 1;
1713 /* /// "nPTPCloseSession()" */
1714 BOOL
nPTPCloseSession(struct NepClassPTP
*nch
)
1717 struct PTPResponse pr
;
1721 po
.po_OpCode
= POC_CLOSESESSION
;
1724 ioerr
= nSendPTPCmd(nch
, &po
);
1727 pr
.pr_TransID
= po
.po_TransID
;
1728 buf
= nGetPTPRsp(nch
, &pr
);
1729 if(nCheckPTPError(nch
, &po
, &pr
))
1736 nch
->nch_SessionID
= 0;
1741 /* /// "nPTPGetObjectHandles()" */
1742 ULONG
* nPTPGetObjectHandles(struct NepClassPTP
*nch
, ULONG storageid
, ULONG objhandle
)
1745 struct PTPResponse pr
;
1749 po
.po_OpCode
= POC_GETOBJECTHANDLES
;
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
);
1758 pr
.pr_TransID
= po
.po_TransID
;
1759 buf
= nGetPTPRsp(nch
, &pr
);
1760 if(nCheckPTPError(nch
, &po
, &pr
))
1765 if(nConvertArrayULONG(nch
, buf
, pr
.pr_DataLength
))
1767 return((ULONG
*) buf
);
1775 /* /// "nPTPFreeObjectInfo()" */
1776 void nPTPFreeObjectInfo(struct NepClassPTP
*nch
, struct PTPObjectInfo
*poi
)
1778 struct PTPObjectInfo
*childpoi
;
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
);
1796 /* /// "nPTPCheckObjectInUse()" */
1797 BOOL
nPTPCheckObjectInUse(struct NepClassPTP
*nch
, struct PTPObjectInfo
*poi
)
1799 struct PTPObjectInfo
*childpoi
;
1805 if(poi
->poi_Flags
& (PTPF_SHARED_LOCK
|PTPF_EXCL_LOCK
))
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
;
1819 /* /// "nPTPGetObjectInfo()" */
1820 struct PTPObjectInfo
* nPTPGetObjectInfo(struct NepClassPTP
*nch
, ULONG objhandle
)
1823 struct PTPResponse pr
;
1827 struct PTPObjectInfo
*poi
;
1830 po
.po_OpCode
= POC_GETOBJECTINFO
;
1832 po
.po_Param
[0] = objhandle
; // object or directory ID
1834 ioerr
= nSendPTPCmd(nch
, &po
);
1837 pr
.pr_TransID
= po
.po_TransID
;
1838 bufptr
= buf
= nGetPTPRsp(nch
, &pr
);
1839 if(nCheckPTPError(nch
, &po
, &pr
))
1844 poi
= nAllocVec(nch
, sizeof(struct PTPObjectInfo
));
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);
1854 poi
->poi_ObjectFmt
= bufptr
[0]|(bufptr
[1]<<8);
1856 protstate
= bufptr
[0]|(bufptr
[1]<<8);
1858 if(protstate
== 0x0001)
1860 poi
->poi_ProtFlags
= FIBF_READ
;
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);
1866 poi
->poi_ThumbFmt
= bufptr
[0]|(bufptr
[1]<<8);
1868 poi
->poi_ThumbSize
= bufptr
[0]|(bufptr
[1]<<8)|(bufptr
[2]<<16)|(bufptr
[3]<<24);
1870 poi
->poi_ThumbWidth
= bufptr
[0]|(bufptr
[1]<<8)|(bufptr
[2]<<16)|(bufptr
[3]<<24);
1872 poi
->poi_ThumbHeight
= bufptr
[0]|(bufptr
[1]<<8)|(bufptr
[2]<<16)|(bufptr
[3]<<24);
1874 poi
->poi_ImageWidth
= bufptr
[0]|(bufptr
[1]<<8)|(bufptr
[2]<<16)|(bufptr
[3]<<24);
1876 poi
->poi_ImageHeight
= bufptr
[0]|(bufptr
[1]<<8)|(bufptr
[2]<<16)|(bufptr
[3]<<24);
1878 poi
->poi_ImageDepth
= bufptr
[0]|(bufptr
[1]<<8)|(bufptr
[2]<<16)|(bufptr
[3]<<24);
1881 poi
->poi_ParentHandle
= bufptr
[0]|(bufptr
[1]<<8)|(bufptr
[2]<<16)|(bufptr
[3]<<24);
1884 //poi->poi_AssType = bufptr[0]|(bufptr[1]<<8);
1886 //poi->poi_AssDesc = bufptr[0]|(bufptr[1]<<8)|(bufptr[2]<<16)|(bufptr[3]<<24);
1888 //poi->poi_SeqNumber = bufptr[0]|(bufptr[1]<<8)|(bufptr[2]<<16)|(bufptr[3]<<24);
1892 poi
->poi_Name
= nGetPimaStrFiltered(nch
, bufptr
);
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
1903 poi
->poi_Keywords
= nGetPimaStr(nch
, bufptr
, NULL
);
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));*/
1928 /* /// "nPTPSendObject()" */
1929 struct PTPObjectInfo
* nPTPSendObject(struct NepClassPTP
*nch
, struct DosPacket
*dp
, struct PTPObjectInfo
*poi
, UBYTE
*databuf
)
1932 struct PTPResponse pr
;
1940 po
.po_OpCode
= POC_SENDOBJECTINFO
;
1942 switch(nch
->nch_NoDestMode
)
1945 po
.po_Param
[0] = poi
->poi_StorageID
;
1946 po
.po_Param
[1] = poi
->poi_ParentHandle
;
1950 po
.po_Param
[0] = poi
->poi_StorageID
;
1959 ioerr
= nSendPTPCmd(nch
, &po
);
1962 dp
->dp_Res2
= ERROR_NOT_A_DOS_DISK
;
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
))
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
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
2013 *bufptr
++ = 0x01; // generic folder
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
);
2031 dp
->dp_Res2
= ERROR_NOT_A_DOS_DISK
;
2035 pr
.pr_TransID
= po
.po_TransID
;
2036 buf
= nGetPTPRsp(nch
, &pr
);
2038 if(nCheckPTPError(nch
, &po
, &pr
))
2040 switch(pr
.pr_RespCode
)
2042 case PRC_STOREREADONLY
:
2043 dp
->dp_Res2
= ERROR_DISK_WRITE_PROTECTED
;
2046 case PRC_ACCESSDENIED
:
2047 dp
->dp_Res2
= ERROR_WRITE_PROTECTED
;
2051 dp
->dp_Res2
= ERROR_DISK_FULL
;
2054 case PRC_INVALIDOBJECTFORMATCODE
:
2055 dp
->dp_Res2
= ERROR_OBJECT_WRONG_TYPE
;
2058 case PRC_SPECIFICATIONOFDESTINATIONUNSUPPORTED
:
2059 if(nch
->nch_NoDestMode
< 2)
2061 nch
->nch_NoDestMode
++;
2066 dp
->dp_Res2
= ERROR_NOT_A_DOS_DISK
;
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];
2087 KPRINTF(5, ("No data stage as size is zero\n"));
2091 po
.po_OpCode
= POC_SENDOBJECT
;
2094 ioerr
= nSendPTPCmd(nch
, &po
);
2097 dp
->dp_Res2
= ERROR_NOT_A_DOS_DISK
;
2101 ioerr
= nSendPTPData(nch
, &po
, databuf
, poi
->poi_Size
);
2104 dp
->dp_Res2
= ERROR_NOT_A_DOS_DISK
;
2107 pr
.pr_TransID
= po
.po_TransID
;
2108 buf
= nGetPTPRsp(nch
, &pr
);
2110 if(nCheckPTPError(nch
, &po
, &pr
))
2112 switch(pr
.pr_RespCode
)
2115 dp
->dp_Res2
= ERROR_DISK_FULL
;
2119 dp
->dp_Res2
= ERROR_NOT_A_DOS_DISK
;
2128 /* /// "nPTPGetStorageIDs()" */
2129 ULONG
* nPTPGetStorageIDs(struct NepClassPTP
*nch
)
2132 struct PTPResponse pr
;
2136 po
.po_OpCode
= POC_GETSTORAGEIDS
;
2139 ioerr
= nSendPTPCmd(nch
, &po
);
2142 pr
.pr_TransID
= po
.po_TransID
;
2143 buf
= nGetPTPRsp(nch
, &pr
);
2144 if(nCheckPTPError(nch
, &po
, &pr
))
2149 if(nConvertArrayULONG(nch
, buf
, pr
.pr_DataLength
))
2151 return((ULONG
*) buf
);
2159 /* /// "nPTPFreeStorageInfo()" */
2160 void nPTPFreeStorageInfo(struct NepClassPTP
*nch
, struct PTPStorageInfo
*psi
)
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
);
2174 /* /// "nPTPGetStorageInfo()" */
2175 struct PTPStorageInfo
* nPTPGetStorageInfo(struct NepClassPTP
*nch
, ULONG storageid
)
2178 struct PTPResponse pr
;
2182 struct PTPStorageInfo
*psi
;
2183 struct PTPObjectInfo
*poi
;
2185 po
.po_OpCode
= POC_GETSTORAGEINFO
;
2187 po
.po_Param
[0] = storageid
;
2189 ioerr
= nSendPTPCmd(nch
, &po
);
2192 pr
.pr_TransID
= po
.po_TransID
;
2193 bufptr
= buf
= nGetPTPRsp(nch
, &pr
);
2194 if(nCheckPTPError(nch
, &po
, &pr
))
2199 psi
= nAllocVec(nch
, sizeof(struct PTPStorageInfo
));
2205 poi
= nAllocVec(nch
, sizeof(struct PTPObjectInfo
));
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);
2218 psi
->psi_FSType
= bufptr
[0]|(bufptr
[1]<<8);
2220 psi
->psi_AccessCaps
= bufptr
[0]|(bufptr
[1]<<8);
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);
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);
2230 psi
->psi_FreeImgs
= bufptr
[0]|(bufptr
[1]<<8)|(bufptr
[2]<<16)|(bufptr
[3]<<24);
2235 psi
->psi_StorageDesc
= nGetPimaStr(nch
, bufptr
, NULL
);
2237 psi
->psi_StorageDesc
= nPsdStrToNStr(nch
, psdCopyStrFmt("Storage_%08lx", psi
->psi_StorageID
));
2239 bufptr
+= (*bufptr
)<<1; // skip Storage Descriptor
2243 psi
->psi_VolumeName
= nGetPimaStrFiltered(nch
, bufptr
);
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
);
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
;
2285 struct PTPResponse pr
;
2287 KPRINTF(10, ("Reading %ld at %ld (%08lx, '%s')\n", len
, pfh
->pfh_SeekPos
, poi
->poi_Handle
, poi
->poi_Name
));
2291 KPRINTF(10, ("No data to read!\n"));
2293 dp
->dp_Res2
= RETURN_OK
;
2297 if(pfh
->pfh_SeekPos
> poi
->poi_Size
)
2299 KPRINTF(10, ("seek pos %ld past size %ld!\n", pfh
->pfh_SeekPos
, poi
->poi_Size
));
2301 dp
->dp_Res2
= ERROR_SEEK_ERROR
;
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
));
2312 dp
->dp_Res2
= RETURN_OK
;
2320 CopyMem(&pfh
->pfh_Buffer
[pfh
->pfh_SeekPos
], buffer
, len
);
2321 pfh
->pfh_SeekPos
+= len
;
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
;
2332 po
.po_Param
[0] = poi
->poi_Handle
;
2333 po
.po_Param
[1] = pfh
->pfh_SeekPos
;
2334 po
.po_Param
[2] = len
;
2336 KPRINTF(10, ("Using GetObject\n"));
2337 po
.po_OpCode
= POC_GETOBJECT
;
2339 po
.po_Param
[0] = poi
->poi_Handle
;
2341 ioerr
= nSendPTPCmd(nch
, &po
);
2344 pr
.pr_TransID
= po
.po_TransID
;
2345 nGetPTPRspData(nch
, &pr
, buffer
, len
);
2346 if(nCheckPTPError(nch
, &po
, &pr
))
2349 dp
->dp_Res2
= ERROR_NOT_A_DOS_DISK
;
2352 pfh
->pfh_SeekPos
+= len
;
2355 dp
->dp_Res2
= ERROR_NOT_A_DOS_DISK
;
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!
2370 KPRINTF(10, ("Using GetObject\n"));
2371 po
.po_OpCode
= POC_GETOBJECT
;
2373 po
.po_Param
[0] = poi
->poi_Handle
;
2374 ioerr
= nSendPTPCmd(nch
, &po
);
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
;
2385 dp
->dp_Res2
= ERROR_NOT_A_DOS_DISK
;
2388 pfh
->pfh_Flags
|= PTPF_OLDLOADED
;
2391 dp
->dp_Res2
= ERROR_NOT_A_DOS_DISK
;
2396 CopyMem(&pfh
->pfh_Buffer
[pfh
->pfh_SeekPos
], buffer
, len
);
2397 pfh
->pfh_SeekPos
+= len
;
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
;
2407 struct PTPResponse pr
;
2411 KPRINTF(10, ("Write %ld at %ld (%08lx, '%s')\n", len
, pfh
->pfh_SeekPos
, poi
->poi_Handle
, poi
->poi_Name
));
2415 KPRINTF(10, ("No data to write\n"));
2419 if(pfh
->pfh_SeekPos
> poi
->poi_Size
)
2421 KPRINTF(10, ("seek pos %ld past size %ld!\n", pfh
->pfh_SeekPos
, poi
->poi_Size
));
2423 dp
->dp_Res2
= ERROR_SEEK_ERROR
;
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
2453 newbuflen
+= 512<<10; // increase buffer by 512 KB;
2456 KPRINTF(10, ("New Buffer length: %ld\n", newbuflen
));
2457 newbuffer
= nAllocVec(nch
, newbuflen
);
2461 dp
->dp_Res2
= ERROR_NO_FREE_STORE
;
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
;
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
;
2483 po
.po_Param
[0] = poi
->poi_Handle
;
2484 ioerr
= nSendPTPCmd(nch
, &po
);
2487 pr
.pr_TransID
= po
.po_TransID
;
2488 nGetPTPRspData(nch
, &pr
, pfh
->pfh_Buffer
, poi
->poi_Size
);
2489 if(nCheckPTPError(nch
, &po
, &pr
))
2492 dp
->dp_Res2
= ERROR_NOT_A_DOS_DISK
;
2495 pfh
->pfh_Flags
|= PTPF_OLDLOADED
;
2498 dp
->dp_Res2
= ERROR_NOT_A_DOS_DISK
;
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
;
2517 /* /// "nPTPSetObjectProtection()" */
2518 void nPTPSetObjectProtection(struct NepClassPTP
*nch
, struct DosPacket
*dp
, struct PTPObjectInfo
*poi
, ULONG protflags
)
2521 struct PTPResponse pr
;
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
;
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
;
2536 po
.po_Param
[1] = 0x0001;
2537 protflags
&= ~(FIBF_WRITE
|FIBF_DELETE
);
2540 ioerr
= nSendPTPCmd(nch
, &po
);
2543 pr
.pr_TransID
= po
.po_TransID
;
2544 buf
= nGetPTPRsp(nch
, &pr
);
2545 if(nCheckPTPError(nch
, &po
, &pr
))
2548 switch(pr
.pr_RespCode
)
2550 case PRC_STOREREADONLY
:
2551 dp
->dp_Res2
= ERROR_DISK_WRITE_PROTECTED
;
2554 case PRC_ACCESSDENIED
:
2555 dp
->dp_Res2
= ERROR_WRITE_PROTECTED
;
2559 dp
->dp_Res2
= ERROR_NOT_A_DOS_DISK
;
2565 dp
->dp_Res2
= ERROR_NOT_A_DOS_DISK
;
2569 poi
->poi_ProtFlags
= protflags
;
2573 /* /// "nPTPFormatStore()" */
2574 void nPTPFormatStore(struct NepClassPTP
*nch
, struct DosPacket
*dp
)
2577 struct PTPResponse pr
;
2580 struct PTPStorageInfo
*psi
;
2581 struct PTPStorageInfo
*nextpsi
;
2582 struct List newinfos
;
2584 KPRINTF(10, ("FormatStore\n"));
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
;
2597 po
.po_OpCode
= POC_FORMATSTORE
;
2599 po
.po_Param
[0] = psi
->psi_StorageID
;
2602 ioerr
= nSendPTPCmd(nch
, &po
);
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
;
2615 case PRC_ACCESSDENIED
:
2616 dp
->dp_Res2
= ERROR_WRITE_PROTECTED
;
2620 dp
->dp_Res2
= ERROR_NOT_A_DOS_DISK
;
2626 Remove(&psi
->psi_Node
);
2627 nPTPFreeStorageInfo(nch
, psi
);
2628 psi
= nPTPGetStorageInfo(nch
, po
.po_Param
[0]);
2631 AddTail(&newinfos
, &psi
->psi_Node
);
2634 dp
->dp_Res2
= ERROR_NOT_A_DOS_DISK
;
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
);
2652 /* /// "nPTPMoveObject()" */
2653 void nPTPMoveObject(struct NepClassPTP
*nch
, struct DosPacket
*dp
, struct PTPObjectInfo
*poi
, struct PTPObjectInfo
*targetdir
)
2656 struct PTPResponse pr
;
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
;
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
);
2669 pr
.pr_TransID
= po
.po_TransID
;
2670 buf
= nGetPTPRsp(nch
, &pr
);
2671 if(nCheckPTPError(nch
, &po
, &pr
))
2674 switch(pr
.pr_RespCode
)
2676 case PRC_STOREREADONLY
:
2677 dp
->dp_Res2
= ERROR_DISK_WRITE_PROTECTED
;
2680 case PRC_ACCESSDENIED
:
2681 dp
->dp_Res2
= ERROR_WRITE_PROTECTED
;
2685 dp
->dp_Res2
= ERROR_NOT_A_DOS_DISK
;
2690 Remove((struct Node
*) poi
);
2691 AddTail((struct List
*) &targetdir
->poi_Children
, (struct Node
*) poi
);
2693 dp
->dp_Res2
= ERROR_NOT_A_DOS_DISK
;
2699 /* /// "nPTPDeleteObject()" */
2700 void nPTPDeleteObject(struct NepClassPTP
*nch
, struct DosPacket
*dp
, struct PTPObjectInfo
*poi
)
2703 struct PTPResponse pr
;
2706 KPRINTF(10, ("DeleteObject %08lx, '%s'\n", poi
->poi_Handle
, poi
->poi_Name
));
2708 po
.po_OpCode
= POC_DELETEOBJECT
;
2710 po
.po_Param
[0] = poi
->poi_Handle
;
2712 ioerr
= nSendPTPCmd(nch
, &po
);
2715 pr
.pr_TransID
= po
.po_TransID
;
2716 buf
= nGetPTPRsp(nch
, &pr
);
2717 if(nCheckPTPError(nch
, &po
, &pr
))
2720 switch(pr
.pr_RespCode
)
2722 case PRC_STOREREADONLY
:
2723 dp
->dp_Res2
= ERROR_DISK_WRITE_PROTECTED
;
2726 case PRC_ACCESSDENIED
:
2727 case PRC_OBJECTWRITEPROTECTED
:
2728 dp
->dp_Res2
= ERROR_WRITE_PROTECTED
;
2732 dp
->dp_Res2
= ERROR_NOT_A_DOS_DISK
;
2738 dp
->dp_Res2
= ERROR_NOT_A_DOS_DISK
;
2744 /* /// "nGetObjFromLock()" */
2745 struct PTPObjectInfo
* nGetObjFromLock(struct NepClassPTP
*nch
, BPTR lock
)
2747 struct FileLock
*fl
= (struct FileLock
*) BADDR(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
);
2759 /* /// "nLoadDirectory()" */
2760 BOOL
nLoadDirectory(struct NepClassPTP
*nch
, struct PTPObjectInfo
*poi
)
2762 ULONG
*idarray
= nPTPGetObjectHandles(nch
, poi
->poi_StorageID
, poi
->poi_Handle
);
2765 struct PTPObjectInfo
*childpoi
;
2767 KPRINTF(10, ("Loading directory for %s\n", poi
->poi_Name
));
2771 KPRINTF(10, ("%ld ObjectHandles:\n", cnt
));
2774 handle
= idarray
[*idarray
- cnt
+ 1];
2775 KPRINTF(1, ("%ld: ObjectHandle %08lx\n", *idarray
- cnt
, handle
));
2776 childpoi
= nPTPGetObjectInfo(nch
, handle
);
2779 childpoi
->poi_Parent
= poi
;
2780 AddTail((struct List
*) &poi
->poi_Children
, (struct Node
*) childpoi
);
2784 nFreeVec(nch
, idarray
);
2785 poi
->poi_Flags
|= PTPF_FETCHED
;
2792 /* /// "nSearchObject()" */
2793 struct PTPObjectInfo
* nSearchObject(struct NepClassPTP
*nch
, struct DosPacket
*dp
, struct PTPObjectInfo
*dirpoi
, STRPTR path
)
2797 struct PTPObjectInfo
*childpoi
;
2801 KPRINTF(10, ("Empty path!\n"));
2805 KPRINTF(10, ("Searching path %s from %s on\n", path
, dirpoi
->poi_Name
));
2808 while(*srcptr
&& (*srcptr
!= '/'))
2812 KPRINTF(5, ("Rooting!\n"));
2813 dirpoi
= &nch
->nch_RootObject
;
2824 KPRINTF(5, ("Object found: %s\n", dirpoi
->poi_Name
));
2828 if((dirpoi
->poi_ObjectFmt
== POF_ASSOCIATION
) && (!(dirpoi
->poi_Flags
& PTPF_FETCHED
)))
2830 nLoadDirectory(nch
, dirpoi
);
2835 KPRINTF(1, ("Going up...\n"));
2836 dirpoi
= dirpoi
->poi_Parent
;
2839 KPRINTF(5, ("Past root!\n"));
2840 dp
->dp_Res2
= ERROR_OBJECT_NOT_FOUND
;
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
;
2858 KPRINTF(1, ("Hash matched for %s on %s\n", childpoi
->poi_Name
, path
));
2860 while(*srcptr
&& *tarptr
&& (*srcptr
!= '/'))
2862 if(nch
->nch_LowCharMap
[*srcptr
] != nch
->nch_LowCharMap
[*tarptr
])
2871 KPRINTF(1, ("Exact match!\n"));
2875 // continue after slash
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
;
2895 KPRINTF(10, ("Can't go into file %s for %s\n", dirpoi
->poi_Name
, path
));
2896 dp
->dp_Res2
= ERROR_INVALID_COMPONENT_NAME
;
2903 /* /// "nGetFileComponent()" */
2904 STRPTR
nGetFileComponent(struct NepClassPTP
*nch
, STRPTR path
)
2906 STRPTR srcptr
= path
;
2907 STRPTR fileptr
= path
;
2913 if((*srcptr
== ':') || (*srcptr
== '/'))
2923 srcptr
= resptr
= nAllocVec(nch
, wordcnt
+ 1);
2926 while((*srcptr
++ = *fileptr
++));
2932 /* /// "nGetPathComponent()" */
2933 STRPTR
nGetPathComponent(struct NepClassPTP
*nch
, STRPTR path
)
2935 STRPTR srcptr
= path
;
2936 STRPTR fileptr
= path
;
2943 fileptr
= srcptr
+ 1;
2945 else if(*srcptr
== '/')
2952 srcptr
= resptr
= nAllocVec(nch
, fileptr
- path
+ 1);
2955 while(path
< fileptr
)
2957 *srcptr
++ = *path
++;
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
;
2975 if(lockmode
!= ACCESS_WRITE
)
2977 lockmode
= ACCESS_READ
; // workaround for bugged programs
2979 fl
= (struct FileLock
*) nAllocVec(nch
, sizeof(struct FileLock
));
2982 dp
->dp_Res2
= ERROR_NO_FREE_STORE
;
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
;
2996 poi
->poi_Flags
|= PTPF_EXCL_LOCK
;
2998 nch
->nch_VolEntry
->dol_misc
.dol_volume
.dol_LockList
= MKBADDR(fl
);
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
));
3012 KPRINTF(10, ("No lock!\n"));
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
);
3021 KPRINTF(1, ("Unlinking at head\n"));
3022 nch
->nch_VolEntry
->dol_misc
.dol_volume
.dol_LockList
= fl
->fl_Link
;
3028 if((struct FileLock
*) BADDR(headfl
->fl_Link
) == fl
)
3031 KPRINTF(1, ("Unlinking in middle\n"));
3032 headfl
->fl_Link
= fl
->fl_Link
;
3036 KPRINTF(20, ("LOCK NOT FOUND IN LIST!\n"));
3039 headfl
= (struct FileLock
*) BADDR(headfl
->fl_Link
);
3044 if(poi
->poi_Flags
& PTPF_SHARED_LOCK
)
3046 if(!(--poi
->poi_ReadLocks
))
3048 poi
->poi_Flags
&= ~PTPF_SHARED_LOCK
;
3051 poi
->poi_Flags
&= ~PTPF_EXCL_LOCK
;
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
;
3066 pfh
= (struct PTPFileHandle
*) nAllocVec(nch
, sizeof(struct PTPFileHandle
));
3069 dp
->dp_Res2
= ERROR_NO_FREE_STORE
;
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
;
3079 poi
->poi_Flags
|= PTPF_EXCL_LOCK
;
3081 AddTail(&nch
->nch_FHs
, &pfh
->pfh_Node
);
3086 /* /// "nFreeFH()" */
3087 void nFreeFH(struct NepClassPTP
*nch
, struct PTPFileHandle
*pfh
)
3089 struct PTPObjectInfo
*poi
;
3091 KPRINTF(1, ("FreeFH(%08lx)\n", pfh
));
3094 KPRINTF(10, ("No FH!\n"));
3097 Remove(&pfh
->pfh_Node
);
3098 nFreeVec(nch
, pfh
->pfh_Buffer
);
3099 poi
= pfh
->pfh_ObjectInfo
;
3101 if(poi
->poi_Flags
& PTPF_SHARED_LOCK
)
3103 if(!(--poi
->poi_ReadLocks
))
3105 poi
->poi_Flags
&= ~PTPF_SHARED_LOCK
;
3108 poi
->poi_Flags
&= ~PTPF_EXCL_LOCK
;
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" },
3127 { POF_MPEG
, "mpg" },
3128 { POF_MPEG
, "mpeg" },
3130 { POF_EXIF_JPEG
, "jpg" },
3131 { POF_EXIF_JPEG
, "jpeg" },
3132 { POF_TIFF
, "tif" },
3133 { POF_TIFF
, "tiff" },
3136 { POF_JFIF
, "jfif" },
3138 { POF_PICT
, "pct" },
3146 /* /// "nGetFormatFromName()" */
3147 UWORD
nGetFormatFromName(struct NepClassPTP
*nch
, STRPTR name
)
3149 STRPTR suffix
= NULL
;
3150 struct ObjectFmtMapping
*ofm
= defaultObjectMapping
;
3160 return POF_UNDEFINED
;
3164 if(stricmp(suffix
, ofm
->ofm_Suffix
) == 0)
3170 return POF_UNDEFINED
;
3174 /* /// "nHandleDOSPackets()" */
3175 void nHandleDOSPackets(struct NepClassPTP
*nch
)
3178 struct MsgPort
*replyport
;
3179 struct DosPacket
*dp
;
3182 struct PTPObjectInfo
*parentdir
;
3183 struct PTPObjectInfo
*poi
;
3184 struct PTPFileHandle
*pfh
;
3187 struct FileLock
*fl
;
3188 struct FileInfoBlock
*fib
;
3189 struct InfoData
*id
;
3190 struct FileHandle
*fh
;
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
;
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
)
3208 nch
->nch_ShallExit
= TRUE
;
3213 nch
->nch_LastObject
= NULL
; // Invalidate last object
3214 nFreeVec(nch
, nch
->nch_LastBuffer
);
3215 nch
->nch_LastBuffer
= NULL
;
3217 case ACTION_INHIBIT
:
3219 case ACTION_IS_FILESYSTEM
:
3223 case ACTION_SAME_LOCK
:
3224 dp
->dp_Res1
= (nGetObjFromLock(nch
, (BPTR
) dp
->dp_Arg1
) == nGetObjFromLock(nch
, (BPTR
) dp
->dp_Arg2
)) ? DOSTRUE
: DOSFALSE
;
3228 nch
->nch_LastObject
= NULL
; // Invalidate last object
3229 nFreeVec(nch
, nch
->nch_LastBuffer
);
3230 nch
->nch_LastBuffer
= NULL
;
3231 nPTPFormatStore(nch
, dp
);
3234 case ACTION_CURRENT_VOLUME
:
3235 dp
->dp_Res1
= (SIPTR
) MKBADDR(nch
->nch_VolEntry
);
3240 case ACTION_DISK_INFO
:
3242 struct PTPStorageInfo
*psi
;
3243 ULONG numblocks
= 0;
3245 ULONG storageid
= 0;
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
;
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))
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
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
;
3291 numblocks
= numfree
;
3293 numblocks
= 1; // make sure we don't get division by zero errors
3296 if(numfree
> numblocks
)
3298 numfree
= numblocks
;
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
;
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
);
3326 if(poi
->poi_ObjectFmt
== POF_ASSOCIATION
)
3328 dp
->dp_Res2
= ERROR_OBJECT_WRONG_TYPE
;
3331 pfh
= nCreateFH(nch
, dp
, poi
, ACCESS_READ
);
3336 fh
->fh_Arg1
= (IPTR
)pfh
;
3339 if(dp
->dp_Action
== ACTION_FINDINPUT
)
3343 KPRINTF(5, ("OpenReadWrite Object '%s', Parent=%s\n", buf
, parentdir
->poi_Name
));
3348 case ACTION_FINDOUTPUT
:
3349 if(!(nch
->nch_DevCaps
& PTPF_SENDOBJ
))
3351 dp
->dp_Res2
= ERROR_DISK_WRITE_PROTECTED
;
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
);
3364 // delete old file first
3365 if(poi
->poi_Flags
& (PTPF_EXCL_LOCK
|PTPF_SHARED_LOCK
))
3367 dp
->dp_Res2
= ERROR_OBJECT_IN_USE
;
3370 if(poi
->poi_ObjectFmt
== POF_ASSOCIATION
)
3372 dp
->dp_Res2
= ERROR_OBJECT_WRONG_TYPE
;
3375 if(poi
->poi_Handle
== 0xffffffff) // cannot delete volume
3377 dp
->dp_Res2
= ERROR_DIR_NOT_FOUND
;
3380 nPTPDeleteObject(nch
, dp
, poi
);
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
);
3396 srcptr
= nGetPathComponent(nch
, buf
);
3399 dp
->dp_Res2
= ERROR_NO_FREE_STORE
;
3402 parentdir
= nSearchObject(nch
, dp
, parentdir
, srcptr
);
3403 nFreeVec(nch
, srcptr
);
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
;
3414 poi
= nAllocVec(nch
, sizeof(struct PTPObjectInfo
));
3417 dp
->dp_Res2
= ERROR_NO_FREE_STORE
;
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
;
3425 poi
->poi_Parent
= parentdir
;
3426 poi
->poi_ParentHandle
= parentdir
->poi_Handle
;
3427 poi
->poi_Name
= nGetFileComponent(nch
, buf
);
3431 dp
->dp_Res2
= ERROR_NO_FREE_STORE
;
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
);
3444 nPTPFreeObjectInfo(nch
, poi
);
3447 pfh
->pfh_Flags
|= PTPF_NEWFILE
|PTPF_MODIFIED
;
3448 fh
->fh_Arg1
= (IPTR
) pfh
;
3449 AddTail((struct List
*) &parentdir
->poi_Children
, (struct Node
*) poi
);
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
;
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
);
3466 dp
->dp_Res2
= ERROR_OBJECT_EXISTS
;
3470 srcptr
= nGetPathComponent(nch
, buf
);
3473 dp
->dp_Res2
= ERROR_NO_FREE_STORE
;
3476 parentdir
= nSearchObject(nch
, dp
, parentdir
, srcptr
);
3477 nFreeVec(nch
, srcptr
);
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
;
3488 poi
= nAllocVec(nch
, sizeof(struct PTPObjectInfo
));
3491 dp
->dp_Res2
= ERROR_NO_FREE_STORE
;
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
;
3499 poi
->poi_Parent
= parentdir
;
3500 poi
->poi_ParentHandle
= parentdir
->poi_Handle
;
3501 poi
->poi_Name
= nGetFileComponent(nch
, buf
);
3505 dp
->dp_Res2
= ERROR_NO_FREE_STORE
;
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
);
3519 AddTail((struct List
*) &parentdir
->poi_Children
, (struct Node
*) poi
);
3520 fl
= nCreateLock(nch
, dp
, poi
, ACCESS_WRITE
);
3523 dp
->dp_Res1
= (SIPTR
) MKBADDR(fl
);
3524 KPRINTF(1, ("Copied lock %08lx\n", dp
->dp_Res1
));
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
;
3542 if(lockmode
== ACCESS_WRITE
)
3544 if(!(nch
->nch_DevCaps
& PTPF_SENDOBJ
))
3546 dp
->dp_Res2
= ERROR_DISK_WRITE_PROTECTED
;
3549 poi
->poi_Flags
&= ~PTPF_EXCL_LOCK
;
3550 pfh
= nCreateFH(nch
, dp
, poi
, ACCESS_WRITE
);
3553 poi
->poi_Flags
|= PTPF_EXCL_LOCK
;
3557 poi
->poi_Flags
|= PTPF_EXCL_LOCK
;
3559 pfh
= nCreateFH(nch
, dp
, poi
, ACCESS_READ
);
3566 pfh
->pfh_SeekPos
= 0;
3567 fh
->fh_Arg1
= (IPTR
)pfh
;
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
);
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
;
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
;
3607 LONG relpos
= dp
->dp_Arg2
;
3608 LONG mode
= dp
->dp_Arg3
;
3611 pfh
= (struct PTPFileHandle
*) dp
->dp_Arg1
;
3612 newpos
= dp
->dp_Res1
= pfh
->pfh_SeekPos
;
3613 poi
= pfh
->pfh_ObjectInfo
;
3617 newpos
= poi
->poi_Size
+ relpos
;
3618 KPRINTF(10, ("Seek from end %ld: %ld\n", relpos
, newpos
));
3621 case OFFSET_CURRENT
:
3623 KPRINTF(10, ("Seek from current %ld: %ld\n", relpos
, newpos
));
3626 case OFFSET_BEGINNING
:
3628 KPRINTF(10, ("Seek from beginning %ld\n", relpos
));
3632 dp
->dp_Res2
= ERROR_SEEK_ERROR
;
3636 if(newpos
> poi
->poi_Size
)
3638 dp
->dp_Res2
= ERROR_SEEK_ERROR
;
3641 pfh
->pfh_SeekPos
= newpos
;
3646 pfh
= (struct PTPFileHandle
*) dp
->dp_Arg1
;
3647 nPTPRead(nch
, dp
, pfh
, (UBYTE
*) dp
->dp_Arg2
, (ULONG
) dp
->dp_Arg3
);
3651 if(!(nch
->nch_DevCaps
& PTPF_SENDOBJ
))
3653 dp
->dp_Res2
= ERROR_DISK_WRITE_PROTECTED
;
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
);
3661 dp
->dp_Res2
= ERROR_WRITE_PROTECTED
;
3665 case ACTION_SET_PROTECT
:
3668 if(!(nch
->nch_DevCaps
& PTPF_PROTOBJ
))
3670 dp
->dp_Res2
= ERROR_DISK_WRITE_PROTECTED
;
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
);
3682 nPTPSetObjectProtection(nch
, dp
, poi
, protflags
);
3687 case ACTION_DELETE_OBJECT
:
3688 if(!(nch
->nch_DevCaps
& PTPF_DELETEOBJ
))
3690 dp
->dp_Res2
= ERROR_DELETE_PROTECTED
;
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
);
3701 if(poi
->poi_Flags
& (PTPF_EXCL_LOCK
|PTPF_SHARED_LOCK
))
3703 dp
->dp_Res2
= ERROR_OBJECT_IN_USE
;
3706 if(poi
->poi_Children
.mlh_Head
->mln_Succ
)
3708 dp
->dp_Res2
= ERROR_DIRECTORY_NOT_EMPTY
;
3711 if(poi
->poi_Handle
== 0xffffffff)
3713 dp
->dp_Res2
= ERROR_DIRECTORY_NOT_EMPTY
;
3716 if(!(poi
->poi_ProtFlags
& FIBF_DELETE
))
3718 dp
->dp_Res2
= ERROR_DELETE_PROTECTED
;
3721 nPTPDeleteObject(nch
, dp
, poi
);
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
;
3734 case ACTION_RENAME_OBJECT
:
3736 struct PTPObjectInfo
*targetdir
;
3739 if(!(nch
->nch_DevCaps
& PTPF_MOVEOBJ
))
3741 dp
->dp_Res2
= ERROR_DISK_WRITE_PROTECTED
;
3745 srcptr
= (UBYTE
*) BADDR(dp
->dp_Arg2
);
3746 tarptr
= (UBYTE
*) BADDR(dp
->dp_Arg4
);
3748 if(*srcptr
++ != *tarptr
++)
3751 KPRINTF(10, ("RenameObject failed: Name lengths different!\n"));
3752 dp
->dp_Res2
= ERROR_RENAME_ACROSS_DEVICES
;
3757 dp
->dp_Res2
= ERROR_INVALID_COMPONENT_NAME
;
3762 if(*srcptr
++ != *tarptr
++)
3764 KPRINTF(10, ("RenameObject failed: Names different!\n"));
3765 dp
->dp_Res2
= ERROR_RENAME_ACROSS_DEVICES
;
3774 parentdir
= nGetObjFromLock(nch
, (BPTR
) dp
->dp_Arg1
);
3775 targetdir
= nGetObjFromLock(nch
, (BPTR
) dp
->dp_Arg3
);
3777 poi
= nSearchObject(nch
, dp
, parentdir
, buf
);
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
);
3789 case ACTION_PARENT_FH
:
3791 if(dp
->dp_Action
== ACTION_PARENT
)
3793 poi
= nGetObjFromLock(nch
, (BPTR
) dp
->dp_Arg1
);
3795 pfh
= (struct PTPFileHandle
*) dp
->dp_Arg1
;
3796 poi
= pfh
->pfh_ObjectInfo
;
3800 fl
= nCreateLock(nch
, dp
, poi
->poi_Parent
, ACCESS_READ
);
3803 dp
->dp_Res1
= (SIPTR
) MKBADDR(fl
);
3804 KPRINTF(1, ("Found parent %08lx\n", dp
->dp_Res1
));
3807 dp
->dp_Res1
= (SIPTR
) NULL
;
3808 // don't set an error code!
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
);
3818 pfh
= (struct PTPFileHandle
*) dp
->dp_Arg1
;
3819 poi
= pfh
->pfh_ObjectInfo
;
3821 fl
= nCreateLock(nch
, dp
, poi
, ACCESS_READ
);
3824 dp
->dp_Res1
= (SIPTR
) MKBADDR(fl
);
3825 KPRINTF(1, ("Copied lock %08lx\n", dp
->dp_Res1
));
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
);
3839 fl
= nCreateLock(nch
, dp
, poi
, lockmode
);
3842 dp
->dp_Res1
= (SIPTR
) MKBADDR(fl
);
3843 KPRINTF(1, ("Found %08lx\n", dp
->dp_Res1
));
3848 case ACTION_EXAMINE_NEXT
:
3849 case ACTION_EXAMINE_OBJECT
:
3850 case ACTION_EXAMINE_FH
:
3851 fib
= (struct FileInfoBlock
*) BADDR(dp
->dp_Arg2
);
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
;
3865 if(!(poi
->poi_Flags
& PTPF_FETCHED
))
3867 nLoadDirectory(nch
, poi
);
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
;
3876 KPRINTF(1, ("Child: %s\n", poi
->poi_Name
));
3877 fib
->fib_DiskKey
= (IPTR
) poi
;
3879 KPRINTF(5, ("Examine (%08lx): '%s'\n", poi
, poi
->poi_Name
));
3880 fib
->fib_DiskKey
= (IPTR
) &poi
->poi_Children
;
3883 pfh
= (struct PTPFileHandle
*) dp
->dp_Arg1
;
3884 poi
= pfh
->pfh_ObjectInfo
;
3886 if(!poi
->poi_Parent
)
3888 fib
->fib_DirEntryType
= ST_ROOT
;
3890 fib
->fib_DirEntryType
= (poi
->poi_ObjectFmt
== POF_ASSOCIATION
) ? ST_USERDIR
: ST_FILE
;
3893 srcptr
= poi
->poi_Name
;
3894 tarptr
= fib
->fib_FileName
+ 1;
3895 while((*tarptr
++ = *srcptr
++))
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
)
3911 srcptr
= poi
->poi_Keywords
;
3912 tarptr
= fib
->fib_Comment
+ 1;
3913 while((*tarptr
++ = *srcptr
++))
3920 fib
->fib_Comment
[0] = cnt
;
3922 /*fib->fib_OwnerUID = 0;
3923 fib->fib_OwnerGID = 0;*/
3926 case ACTION_FREE_LOCK
:
3927 fl
= (struct FileLock
*) BADDR(dp
->dp_Arg1
);
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
;
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
;
3947 mn
->mn_Node
.ln_Name
= (STRPTR
) dp
;
3948 mn
->mn_Node
.ln_Pred
= mn
->mn_Node
.ln_Succ
= NULL
;
3949 PutMsg(replyport
, mn
);
3954 /* /// "nPTPTask()" */
3955 AROS_UFH0(void, nPTPTask
)
3959 struct NepClassPTP
*nch
;
3960 //struct PsdPipe *pp;
3963 //UBYTE eventbuf[24];
3966 BOOL reportlocks
= TRUE
;
3967 BOOL reportfhs
= TRUE
;
3969 if((nch
= nAllocPTP()))
3972 if(nch
->nch_ReadySigTask
)
3974 Signal(nch
->nch_ReadySigTask
, 1L<<nch
->nch_ReadySignal
);
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
);
3990 struct PTPStorageInfo
*psi
;
3994 KPRINTF(10, ("%ld StorageIDs:\n", 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
);
4009 struct DosList
*dol
;
4010 dol
= nch
->nch_DevEntry
;
4012 dol
->dol_Type
= DLT_DEVICE
;
4013 dol
->dol_Task
= nch
->nch_DOSMsgPort
;
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
;
4027 dol
->dol_Type
= DLT_VOLUME
;
4028 dol
->dol_Task
= nch
->nch_DOSMsgPort
;
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
;
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
;
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
;
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
));
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
;
4098 KPRINTF(10, ("Still filehandles there.\n"));
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));
4141 KPRINTF(1, ("Int Pipe failed %ld\n", ioerr));
4144 if(!nch->nch_ShallExit)
4146 psdSendPipe(nch->nch_EPIntPipe, eventbuf, 20);
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);*/
4165 /* /// "nAllocPTP()" */
4166 struct NepClassPTP
* nAllocPTP(void)
4168 struct NepPTPBase
*nh
;
4169 struct Task
*thistask
;
4170 struct NepClassPTP
*nch
;
4171 struct PTPObjectInfo
*poi
;
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"));
4185 if(!(nch
->nch_Base
= OpenLibrary("poseidon.library", 4)))
4190 if(!(nch
->nch_DOSBase
= OpenLibrary("dos.library", 36)))
4192 Alert(AG_OpenLib
|AO_DOSLib
);
4195 nch
->nch_MemPool
= CreatePool(MEMF_CLEAR
|MEMF_PUBLIC
, 16384, 128);
4196 if(!nch
->nch_MemPool
)
4200 psdGetAttrs(PGA_INTERFACE
, nch
->nch_Interface
,
4201 IFA_Config
, &nch
->nch_Config
,
4202 IFA_InterfaceNum
, &nch
->nch_IfNum
,
4204 psdGetAttrs(PGA_CONFIG
, nch
->nch_Config
,
4205 CA_Device
, &nch
->nch_Device
,
4208 nch
->nch_EPIn
= psdFindEndpoint(nch
->nch_Interface
, NULL
,
4210 EA_TransferType
, USEAF_BULK
,
4212 nch
->nch_EPOut
= psdFindEndpoint(nch
->nch_Interface
, NULL
,
4214 EA_TransferType
, USEAF_BULK
,
4216 nch
->nch_EPInt
= psdFindEndpoint(nch
->nch_Interface
, NULL
,
4218 EA_TransferType
, USEAF_INTERRUPT
,
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"));
4227 psdGetAttrs(PGA_ENDPOINT
, nch
->nch_EPIn
,
4228 EA_MaxPktSize
, &nch
->nch_EPInPktSize
,
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
;
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,
4271 psdSetAttrs(PGA_PIPE
, nch
->nch_EPOutPipe
,
4272 PPA_NoZeroPktTerm
, FALSE
,
4273 PPA_NakTimeout
, TRUE
,
4274 PPA_NakTimeoutTime
, 5000,
4276 nch
->nch_Task
= thistask
;
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
);
4293 CloseLibrary(nch
->nch_DOSBase
);
4294 nch
->nch_DOSBase
= NULL
;
4295 CloseLibrary(nch
->nch_Base
);
4297 nch
->nch_Task
= NULL
;
4298 if(nch
->nch_ReadySigTask
)
4300 Signal(nch
->nch_ReadySigTask
, 1L<<nch
->nch_ReadySignal
);
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
);
4333 nch
->nch_Task
= NULL
;
4334 if(nch
->nch_ReadySigTask
)
4336 Signal(nch
->nch_ReadySigTask
, 1L<<nch
->nch_ReadySignal
);
4341 /**************************************************************************/
4343 /* /// "nGUITask()" */
4344 AROS_UFH0(void, nGUITask
)
4348 struct Task
*thistask
;
4349 struct NepPTPBase
*nh
;
4350 struct NepClassPTP
*nch
;
4353 thistask
= FindTask(NULL
);
4355 #define ps nch->nch_PsdBase
4356 #undef IntuitionBase
4357 #define IntuitionBase nch->nch_IntBase
4358 #undef MUIMasterBase
4359 #define MUIMasterBase nch->nch_MUIBase
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
);
4374 if(!(IntuitionBase
= OpenLibrary("intuition.library", 39)))
4376 KPRINTF(10, ("Couldn't open intuition.library.\n"));
4377 nGUITaskCleanup(nch
);
4380 if(!(ps
= OpenLibrary("poseidon.library", 4)))
4382 KPRINTF(10, ("Couldn't open poseidon.library.\n"));
4383 nGUITaskCleanup(nch
);
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
)"?",
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",
4407 Child
, (IPTR
)(nch
->nch_SetDefaultMI
= MenuitemObject
,
4408 MUIA_Menuitem_Title
, (IPTR
)"Save as Default",
4409 MUIA_Menuitem_Shortcut
, (IPTR
)"D",
4411 Child
, (IPTR
)MenuitemObject
,
4412 MUIA_Menuitem_Title
, (IPTR
)NM_BARLABEL
,
4414 Child
, (IPTR
)(nch
->nch_MUIPrefsMI
= MenuitemObject
,
4415 MUIA_Menuitem_Title
, (IPTR
)"MUI Settings",
4416 MUIA_Menuitem_Shortcut
, (IPTR
)"M",
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
,
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,
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
,
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
,
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
,
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
,
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
,
4470 MUIA_InputMode
, MUIV_InputMode_RelVerify
,
4471 MUIA_Text_Contents
, (IPTR
)"\33c Save ",
4473 Child
, (IPTR
)(nch
->nch_SetDefaultObj
= TextObject
, ButtonFrame
,
4474 MUIA_Background
, MUII_ButtonBack
,
4476 MUIA_InputMode
, MUIV_InputMode_RelVerify
,
4477 MUIA_Text_Contents
, (IPTR
)(nch
->nch_Interface
? "\33c Save as Default " : "\33c Save Defaults "),
4479 Child
, (IPTR
)(nch
->nch_CloseObj
= TextObject
, ButtonFrame
,
4480 MUIA_Background
, MUII_ButtonBack
,
4482 MUIA_InputMode
, MUIV_InputMode_RelVerify
,
4483 MUIA_Text_Contents
, (IPTR
)"\33c Use ",
4492 KPRINTF(10, ("Couldn't create application\n"));
4493 nGUITaskCleanup(nch
);
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);
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
);
4532 retid
= DoMethod(nch
->nch_App
, MUIM_Application_NewInput
, &sigs
);
4536 case ID_STORE_CONFIG
:
4537 case MUIV_Application_ReturnID_Quit
:
4541 get(nch
->nch_EnableMTPObj
, MUIA_Selected
, &nch
->nch_CDC
->cdc_EnableMTP
);
4542 get(nch
->nch_NoPartObjObj
, MUIA_Selected
, &nch
->nch_CDC
->cdc_NoPartObj
);
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
);
4552 psdSetClsCfg(libname
, NULL
);
4553 pic
= psdGetClsCfg(libname
);
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
);
4568 psdSetUsbDevCfg(libname
, nch
->nch_DevIDString
, nch
->nch_IfIDString
, NULL
);
4569 pic
= psdGetUsbDevCfg(libname
, nch
->nch_DevIDString
, nch
->nch_IfIDString
);
4573 if(psdAddCfgEntry(pic
, nch
->nch_CDC
))
4575 if(retid
!= MUIV_Application_ReturnID_Quit
)
4577 psdSaveCfgToDisk(NULL
, FALSE
);
4579 retid
= MUIV_Application_ReturnID_Quit
;
4583 retid
= MUIV_Application_ReturnID_Quit
;
4589 MUI_RequestA(nch
->nch_App
, nch
->nch_MainWindow
, 0, NULL
, "Moo!", VERSION_STRING
, NULL
);
4592 if(retid
== MUIV_Application_ReturnID_Quit
)
4598 sigs
= Wait(sigs
| sigmask
| SIGBREAKF_CTRL_C
);
4599 if(sigs
& SIGBREAKF_CTRL_C
)
4605 set(nch
->nch_MainWindow
, MUIA_Window_Open
, FALSE
);
4607 nGUITaskCleanup(nch
);
4613 /* /// "nGUITaskCleanup()" */
4614 void nGUITaskCleanup(struct NepClassPTP
*nch
)
4618 MUI_DisposeObject(nch
->nch_App
);
4619 nch
->nch_App
= NULL
;
4623 CloseLibrary(MUIMasterBase
);
4624 MUIMasterBase
= NULL
;
4628 CloseLibrary(IntuitionBase
);
4629 IntuitionBase
= NULL
;
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
;