1 /* dev.c - usbpalm.device by Chris Hodges
6 #include "palmpda.class.h"
8 AROS_UFH3(DEVBASETYPEPTR
, devInit
,
9 AROS_UFHA(DEVBASETYPEPTR
, base
, D0
),
10 AROS_UFHA(BPTR
, seglist
, A0
),
11 AROS_UFHA(struct ExecBase
*, SysBase
, A6
))
15 KPRINTF(10, ("devInit base: 0x%08lx seglist: 0x%08lx SysBase: 0x%08lx\n",
16 base
, seglist
, SysBase
));
18 base
->np_Library
.lib_Node
.ln_Type
= NT_DEVICE
;
19 base
->np_Library
.lib_Node
.ln_Name
= DEVNAME
;
20 base
->np_Library
.lib_Flags
= LIBF_SUMUSED
|LIBF_CHANGED
;
21 base
->np_Library
.lib_Version
= VERSION_NUMBER
;
22 base
->np_Library
.lib_Revision
= REVISION_NUMBER
;
23 base
->np_Library
.lib_IdString
= VERSION_STRING
;
26 base
->np_SegList
= seglist
;
28 if((base
->np_UtilityBase
= OpenLibrary("utility.library", 0)))
30 KPRINTF(10, ("devInit: Ok\n"));
31 KPRINTF(10, ("devInit: openCnt = %ld\n", base
->np_Library
.lib_OpenCnt
));
44 #define UtilityBase base->np_UtilityBase
46 AROS_LH3(DEVBASETYPEPTR
, devOpen
,
47 AROS_LHA(struct IOExtSer
*, ioreq
, A1
),
48 AROS_LHA(ULONG
, unit
, D0
),
49 AROS_LHA(ULONG
, flags
, D1
),
50 DEVBASETYPEPTR
, base
, 1, dev
)
54 struct NepClassSerial
*ncp
;
56 KPRINTF(10, ("devOpen ioreq: 0x%08lx unit: %ld flags: 0x%08lx base: 0x%08lx\n",
57 ioreq
, unit
, flags
, base
));
59 ++base
->np_Library
.lib_OpenCnt
;
60 base
->np_Library
.lib_Flags
&= ~LIBF_DELEXP
;
62 KPRINTF(10, ("devOpen: openCnt = %ld\n", base
->np_Library
.lib_OpenCnt
));
63 /* Damn f*cking programs which leave this field to zero! */
64 if(ioreq
->IOSer
.io_Message
.mn_Length
&& (ioreq
->IOSer
.io_Message
.mn_Length
< sizeof(struct IOExtSer
)))
66 KPRINTF(20, ("devOpen: invalid MN_LENGTH (%ld < %ld)!\n",
67 ioreq
->IOSer
.io_Message
.mn_Length
, sizeof(struct IOExtSer
)));
69 ioreq
->IOSer
.io_Error
= IOERR_BADLENGTH
;
71 /* Default to open failure. */
72 ioreq
->IOSer
.io_Error
= IOERR_OPENFAIL
;
74 ioreq
->IOSer
.io_Unit
= NULL
;
75 ncp
= (struct NepClassSerial
*) base
->np_ClsBase
->nh_Units
.lh_Head
;
76 while(ncp
->ncp_Unit
.unit_MsgPort
.mp_Node
.ln_Succ
)
78 if(ncp
->ncp_UnitNo
== unit
)
80 if(ncp
->ncp_Unit
.unit_OpenCnt
)
82 ioreq
->IOSer
.io_Error
= IOERR_UNITBUSY
;
84 ioreq
->IOSer
.io_Unit
= (struct Unit
*) ncp
;
88 ncp
= (struct NepClassSerial
*) ncp
->ncp_Unit
.unit_MsgPort
.mp_Node
.ln_Succ
;
91 if(!ioreq
->IOSer
.io_Unit
)
95 KPRINTF(20, ("devOpen: unit not allocated, opening anyway!\n"));
96 //ioreq->IOSer.io_Unit = &base->np_ClsBase->nh_DummyUnit;
97 ioreq
->IOSer
.io_Message
.mn_Node
.ln_Type
= NT_REPLYMSG
;
98 ioreq
->IOSer
.io_Error
= 0;
100 ioreq
->io_CtlChar
= SER_DEFAULT_CTLCHAR
;
101 ioreq
->io_RBufLen
= 2048;
102 ioreq
->io_ExtFlags
= 0;
103 ioreq
->io_Baud
= 9600;
104 ioreq
->io_BrkTime
= 250000;
105 ioreq
->io_TermArray
.TermArray0
= 0;
106 ioreq
->io_TermArray
.TermArray1
= 0;
107 ioreq
->io_ReadLen
= 8;
108 ioreq
->io_WriteLen
= 8;
109 ioreq
->io_StopBits
= 1;
110 if(ioreq
->io_SerFlags
& SERF_RAD_BOOGIE
)
112 ioreq
->io_SerFlags
|= SERF_XDISABLED
;
113 ioreq
->io_SerFlags
&= ~SERF_PARTY_ON
|SERF_PARTY_ODD
;
118 ioreq
->IOSer
.io_Message
.mn_Node
.ln_Type
= NT_REPLYMSG
;
119 ioreq
->IOSer
.io_Error
= 0;
120 ioreq
->IOSer
.io_Unit
->unit_OpenCnt
++;
122 ioreq
->io_CtlChar
= SER_DEFAULT_CTLCHAR
;
123 ioreq
->io_RBufLen
= 2048;
124 ioreq
->io_ExtFlags
= 0;
125 ioreq
->io_Baud
= 9600;
126 ioreq
->io_BrkTime
= 250000;
127 ioreq
->io_TermArray
.TermArray0
= 0;
128 ioreq
->io_TermArray
.TermArray1
= 0;
129 ioreq
->io_ReadLen
= 8;
130 ioreq
->io_WriteLen
= 8;
131 ioreq
->io_StopBits
= 1;
132 if(ioreq
->io_SerFlags
& SERF_RAD_BOOGIE
)
134 ioreq
->io_SerFlags
|= SERF_XDISABLED
;
135 ioreq
->io_SerFlags
&= ~SERF_PARTY_ON
|SERF_PARTY_ODD
;
139 ncp
->ncp_DenyRequests
= FALSE
;
140 /* initial settings */
141 ioreq
->IOSer
.io_Command
= SDCMD_SETPARAMS
;
142 ioreq
->IOSer
.io_Flags
&= ~IOF_QUICK
;
143 PutMsg(&ncp
->ncp_Unit
.unit_MsgPort
, (struct Message
*) ioreq
);
144 while(!GetMsg(&ncp
->ncp_Unit
.unit_MsgPort
))
146 WaitPort(&ncp
->ncp_Unit
.unit_MsgPort
);
152 ioreq
->IOSer
.io_Unit
= (APTR
) -1;
153 ioreq
->IOSer
.io_Device
= (APTR
) -1;
154 base
->np_Library
.lib_OpenCnt
--;
162 AROS_LH1(BPTR
, devClose
,
163 AROS_LHA(struct IOExtSer
*, ioreq
, A1
),
164 DEVBASETYPEPTR
, base
, 2, dev
)
169 struct NepClassSerial
*ncp
= (struct NepClassSerial
*) ioreq
->IOSer
.io_Unit
;
171 KPRINTF(10, ("devClose ioreq: 0x%08lx base: 0x%08lx\n", ioreq
, base
));
175 if(ncp
)//(struct Unit *) ncp != &base->np_ClsBase->nh_DummyUnit)
177 /* Don't allow queuing */
178 ncp
->ncp_DenyRequests
= TRUE
;
179 /* close connection */
180 ioreq
->IOSer
.io_Command
= CMD_INVALID
;
181 ioreq
->IOSer
.io_Flags
&= ~IOF_QUICK
;
182 PutMsg(&ncp
->ncp_Unit
.unit_MsgPort
, (struct Message
*) ioreq
);
183 while(!GetMsg(&ncp
->ncp_Unit
.unit_MsgPort
))
185 WaitPort(&ncp
->ncp_Unit
.unit_MsgPort
);
187 ncp
->ncp_Unit
.unit_OpenCnt
--;
189 ioreq
->IOSer
.io_Unit
= (APTR
) -1;
190 ioreq
->IOSer
.io_Device
= (APTR
) -1;
192 if(--base
->np_Library
.lib_OpenCnt
== 0)
194 if(base
->np_Library
.lib_Flags
& LIBF_DELEXP
)
196 KPRINTF(5, ("devClose: calling expunge...\n"));
197 ret
= AROS_LC1(BPTR
, devExpunge
,
198 AROS_LCA(DEVBASETYPEPTR
, base
, D0
),
199 DEVBASETYPEPTR
, base
, 3, dev
);
203 KPRINTF(5, ("devClose: lib_OpenCnt = %ld\n", base
->np_Library
.lib_OpenCnt
));
211 AROS_LH1(BPTR
, devExpunge
,
212 AROS_LHA(DEVBASETYPEPTR
, extralh
, D0
),
213 DEVBASETYPEPTR
, base
, 3, dev
)
219 KPRINTF(10, ("devExpunge base: 0x%08lx\n", base
));
223 if(base
->np_Library
.lib_OpenCnt
== 0)
225 KPRINTF(5, ("devExpunge: Unloading...\n"));
227 CloseLibrary(base
->np_UtilityBase
);
229 ret
= base
->np_SegList
;
231 KPRINTF(5, ("devExpunge: removing device node 0x%08lx\n",
232 &base
->np_Library
.lib_Node
));
233 Remove(&base
->np_Library
.lib_Node
);
235 KPRINTF(5, ("devExpunge: FreeMem()...\n"));
236 FreeMem((char *) base
- base
->np_Library
.lib_NegSize
,
237 (ULONG
) (base
->np_Library
.lib_NegSize
+ base
->np_Library
.lib_PosSize
));
239 KPRINTF(5, ("devExpunge: Unloading done! " DEVNAME
" expunged!\n\n"));
245 KPRINTF(5, ("devExpunge: Could not expunge, LIBF_DELEXP set!\n"));
246 base
->np_Library
.lib_Flags
|= LIBF_DELEXP
;
254 AROS_LH0(DEVBASETYPEPTR
, devReserved
,
255 DEVBASETYPEPTR
, base
, 4, dev
)
262 AROS_LH1(void, devBeginIO
,
263 AROS_LHA(struct IOExtSer
*, ioreq
, A1
),
264 DEVBASETYPEPTR
, base
, 5, dev
)
268 struct NepClassSerial
*ncp
= (struct NepClassSerial
*) ioreq
->IOSer
.io_Unit
;
269 WORD ret
= IOERR_NOCMD
;
271 KPRINTF(1, ("devBeginIO ioreq: 0x%08lx base: 0x%08lx cmd: %lu len: %ld\n", ioreq
, base
, ioreq
->IOSer
.io_Command
, ioreq
->IOSer
.io_Length
));
273 ioreq
->IOSer
.io_Message
.mn_Node
.ln_Type
= NT_MESSAGE
;
274 ioreq
->IOSer
.io_Error
= 0;
276 if(ioreq
->IOSer
.io_Command
< NSCMD_DEVICEQUERY
)
278 if(!ncp
)//(struct Unit *) ncp == &base->np_ClsBase->nh_DummyUnit)
280 /* see, if unit arrived in the meanwhile? */
281 ncp
= (struct NepClassSerial
*) base
->np_ClsBase
->nh_Units
.lh_Head
;
282 while(ncp
->ncp_Unit
.unit_MsgPort
.mp_Node
.ln_Succ
)
284 if(!ncp
->ncp_Unit
.unit_OpenCnt
)
286 ioreq
->IOSer
.io_Unit
= (struct Unit
*) ncp
;
287 ioreq
->IOSer
.io_Unit
->unit_OpenCnt
++;
288 ncp
->ncp_DenyRequests
= FALSE
;
289 /* FIXME: Need call to SDCMD_SETPARAMS */
292 ncp
= (struct NepClassSerial
*) ncp
->ncp_Unit
.unit_MsgPort
.mp_Node
.ln_Succ
;
294 ncp
= (struct NepClassSerial
*) ioreq
->IOSer
.io_Unit
;
296 if(ncp
)//(struct Unit *) ncp != &base->np_ClsBase->nh_DummyUnit)
298 switch (ioreq
->IOSer
.io_Command
)
301 if(ncp
->ncp_EPInStream
&& (!ncp
->ncp_DenyRequests
))
303 ioreq
->IOSer
.io_Flags
&= ~IOF_QUICK
;
305 AddTail(&ncp
->ncp_ReadQueue
, &ioreq
->IOSer
.io_Message
.mn_Node
);
308 Signal(ncp
->ncp_Task
, 1UL<<ncp
->ncp_TaskMsgPort
->mp_SigBit
);
318 if(!ncp
->ncp_DenyRequests
)
320 if(ioreq
->IOSer
.io_Length
== -1)
322 ioreq
->IOSer
.io_Length
= strlen(ioreq
->IOSer
.io_Data
);
324 ioreq
->IOSer
.io_Flags
&= ~IOF_QUICK
;
326 AddTail(&ncp
->ncp_WriteQueue
, &ioreq
->IOSer
.io_Message
.mn_Node
);
329 Signal(ncp
->ncp_Task
, 1UL<<ncp
->ncp_TaskMsgPort
->mp_SigBit
);
339 ncp
->ncp_DevSuspend
= FALSE
;
344 ncp
->ncp_DevSuspend
= TRUE
;
349 ioreq->IOSer.io_Actual = 1;
350 ioreq->io_Status = 0;*/
359 case SDCMD_SETPARAMS
:
360 if(!ncp
->ncp_DenyRequests
)
362 ioreq
->IOSer
.io_Flags
&= ~IOF_QUICK
;
364 PutMsg(&ncp
->ncp_Unit
.unit_MsgPort
, (struct Message
*) ioreq
);
366 ioreq
->IOSer
.io_Actual
= 0;
380 switch(ioreq
->IOSer
.io_Command
)
382 case NSCMD_DEVICEQUERY
:
383 ret
= cmdNSDeviceQuery((struct IOStdReq
*) ioreq
, ncp
, base
);
392 if(ret
!= RC_DONTREPLY
)
394 KPRINTF(1, ("TermIO\n"));
399 ioreq
->IOSer
.io_Error
= ret
& 0xff;
401 /* Terminate the iorequest
409 AROS_LH1(LONG
, devAbortIO
,
410 AROS_LHA(struct IOExtSer
*, ioreq
, A1
),
411 DEVBASETYPEPTR
, base
, 6, dev
)
415 struct NepClassSerial
*ncp
= (struct NepClassSerial
*) ioreq
->IOSer
.io_Unit
;
416 struct IOExtSer
*iocmp
;
418 KPRINTF(5, ("devAbortIO ioreq: 0x%08lx\n", ioreq
));
420 if(!ncp
)//(struct Unit *) ncp != &base->np_ClsBase->nh_DummyUnit)
428 if(ioreq
->IOSer
.io_Message
.mn_Node
.ln_Type
== NT_MESSAGE
)
430 /* check if it's the writing pipe */
431 if(ioreq
== ncp
->ncp_WritePending
)
433 if(ncp
->ncp_AbortSignal
>= 0)
435 /* prod the subtask */
436 Signal(ncp
->ncp_Task
, 1UL<<ncp
->ncp_AbortSignal
);
441 iocmp
= (struct IOExtSer
*) ncp
->ncp_ReadQueue
.lh_Head
;
442 while(iocmp
->IOSer
.io_Message
.mn_Node
.ln_Succ
)
446 Remove((struct Node
*) ioreq
);
447 ioreq
->IOSer
.io_Error
= IOERR_ABORTED
;
448 ReplyMsg(&ioreq
->IOSer
.io_Message
);
452 iocmp
= (struct IOExtSer
*) iocmp
->IOSer
.io_Message
.mn_Node
.ln_Succ
;
454 iocmp
= (struct IOExtSer
*) ncp
->ncp_WriteQueue
.lh_Head
;
455 while(iocmp
->IOSer
.io_Message
.mn_Node
.ln_Succ
)
459 Remove((struct Node
*)ioreq
);
460 ioreq
->IOSer
.io_Error
= IOERR_ABORTED
;
461 ReplyMsg(&ioreq
->IOSer
.io_Message
);
465 iocmp
= (struct IOExtSer
*) iocmp
->IOSer
.io_Message
.mn_Node
.ln_Succ
;
478 const UWORD NSDSupported
[] =
480 CMD_CLEAR
, CMD_RESET
,
482 CMD_WRITE
, CMD_START
,
483 CMD_STOP
, SDCMD_QUERY
,
489 WORD
cmdNSDeviceQuery(struct IOStdReq
*ioreq
,
490 struct NepClassSerial
*ncp
,
491 struct NepSerDevBase
*base
)
493 struct my_NSDeviceQueryResult
*query
;
495 query
= (struct my_NSDeviceQueryResult
*) ioreq
->io_Data
;
497 KPRINTF(10, ("NSCMD_DEVICEQUERY ioreq: 0x%08lx query: 0x%08lx\n", ioreq
, query
));
504 (ioreq
->io_Length
< sizeof(struct my_NSDeviceQueryResult
)) ||
505 (query
->DevQueryFormat
!= 0) ||
506 (query
->SizeAvailable
!= 0))
508 /* Return error. This is special handling, since iorequest is only
509 guaranteed to be sizeof(struct IOStdReq). If we'd let our
510 devBeginIO dispatcher return the error, it would trash some
511 memory past end of the iorequest (ios2_WireError field).
513 ioreq
->io_Error
= IOERR_NOCMD
;
514 TermIO((struct IOExtSer
*) ioreq
, base
);
516 /* Don't reply, we already did.
521 ioreq
->io_Actual
= query
->SizeAvailable
522 = sizeof(struct my_NSDeviceQueryResult
);
523 query
->DeviceType
= NSDEVTYPE_SERIAL
;
524 query
->DeviceSubType
= 0;
525 query
->SupportedCommands
= NSDSupported
;
527 /* Return success (note that this will NOT poke ios2_WireError).
533 *===========================================================
534 * TermIO(ioreq, base)
535 *===========================================================
537 * Return completed ioreq to sender.
541 void TermIO(struct IOExtSer
*ioreq
,
542 struct NepSerDevBase
*base
)
544 ioreq
->IOSer
.io_Message
.mn_Node
.ln_Type
= NT_FREEMSG
;
546 /* If not quick I/O, reply the message
548 if(!(ioreq
->IOSer
.io_Flags
& IOF_QUICK
))
550 ReplyMsg(&ioreq
->IOSer
.io_Message
);