poseidon: Fix a number of BPTR issues
[AROS.git] / rom / usb / classes / palmpda / dev.c
blobe3b99203fcc90f374dc87a2accafa9176b07633f
1 /* dev.c - usbpalm.device by Chris Hodges
2 */
4 #include "debug.h"
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))
13 AROS_USERFUNC_INIT
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;
25 /* Store segment */
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));
32 return(base);
34 else
36 return(NULL);
38 return(base);
40 AROS_USERFUNC_EXIT
43 #undef UtilityBase
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)
52 AROS_LIBFUNC_INIT
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;
70 } else {
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;
83 } else {
84 ioreq->IOSer.io_Unit = (struct Unit *) ncp;
86 break;
88 ncp = (struct NepClassSerial *) ncp->ncp_Unit.unit_MsgPort.mp_Node.ln_Succ;
91 if(!ioreq->IOSer.io_Unit)
93 /* Deaf opening
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;
115 return base;
116 } else {
117 /* Opended ok! */
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;
138 /* Allow queuing */
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);
148 return base;
152 ioreq->IOSer.io_Unit = (APTR) -1;
153 ioreq->IOSer.io_Device = (APTR) -1;
154 base->np_Library.lib_OpenCnt--;
156 return(NULL);
158 AROS_LIBFUNC_EXIT
162 AROS_LH1(BPTR, devClose,
163 AROS_LHA(struct IOExtSer *, ioreq, A1),
164 DEVBASETYPEPTR, base, 2, dev)
166 AROS_LIBFUNC_INIT
168 BPTR ret;
169 struct NepClassSerial *ncp = (struct NepClassSerial *) ioreq->IOSer.io_Unit;
171 KPRINTF(10, ("devClose ioreq: 0x%08lx base: 0x%08lx\n", ioreq, base));
173 ret = BNULL;
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));
205 return(ret);
207 AROS_LIBFUNC_EXIT
211 AROS_LH1(BPTR, devExpunge,
212 AROS_LHA(DEVBASETYPEPTR, extralh, D0),
213 DEVBASETYPEPTR, base, 3, dev)
215 AROS_LIBFUNC_INIT
217 BPTR ret;
219 KPRINTF(10, ("devExpunge base: 0x%08lx\n", base));
221 ret = BNULL;
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"));
241 return(ret);
243 else
245 KPRINTF(5, ("devExpunge: Could not expunge, LIBF_DELEXP set!\n"));
246 base->np_Library.lib_Flags |= LIBF_DELEXP;
249 return(BNULL);
251 AROS_LIBFUNC_EXIT
254 AROS_LH0(DEVBASETYPEPTR, devReserved,
255 DEVBASETYPEPTR, base, 4, dev)
257 AROS_LIBFUNC_INIT
258 return NULL;
259 AROS_LIBFUNC_EXIT
262 AROS_LH1(void, devBeginIO,
263 AROS_LHA(struct IOExtSer *, ioreq, A1),
264 DEVBASETYPEPTR, base, 5, dev)
266 AROS_LIBFUNC_INIT
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 */
290 break;
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)
300 case CMD_READ:
301 if(ncp->ncp_EPInStream && (!ncp->ncp_DenyRequests))
303 ioreq->IOSer.io_Flags &= ~IOF_QUICK;
304 Forbid();
305 AddTail(&ncp->ncp_ReadQueue, &ioreq->IOSer.io_Message.mn_Node);
306 if(ncp->ncp_Task)
308 Signal(ncp->ncp_Task, 1UL<<ncp->ncp_TaskMsgPort->mp_SigBit);
310 Permit();
311 ret = RC_DONTREPLY;
312 } else {
313 ret = IOERR_ABORTED;
315 break;
317 case CMD_WRITE:
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;
325 Forbid();
326 AddTail(&ncp->ncp_WriteQueue, &ioreq->IOSer.io_Message.mn_Node);
327 if(ncp->ncp_Task)
329 Signal(ncp->ncp_Task, 1UL<<ncp->ncp_TaskMsgPort->mp_SigBit);
331 Permit();
332 ret = RC_DONTREPLY;
333 } else {
334 ret = IOERR_ABORTED;
336 break;
338 case CMD_START:
339 ncp->ncp_DevSuspend = FALSE;
340 ret = RC_OK;
341 break;
343 case CMD_STOP:
344 ncp->ncp_DevSuspend = TRUE;
345 ret = RC_OK;
346 break;
348 /*case SDCMD_QUERY:
349 ioreq->IOSer.io_Actual = 1;
350 ioreq->io_Status = 0;*/
351 case SDCMD_BREAK:
352 ret = RC_OK;
353 break;
355 case CMD_CLEAR:
356 case CMD_RESET:
357 case CMD_FLUSH:
358 case SDCMD_QUERY:
359 case SDCMD_SETPARAMS:
360 if(!ncp->ncp_DenyRequests)
362 ioreq->IOSer.io_Flags &= ~IOF_QUICK;
363 ret = RC_DONTREPLY;
364 PutMsg(&ncp->ncp_Unit.unit_MsgPort, (struct Message *) ioreq);
365 } else {
366 ioreq->IOSer.io_Actual = 0;
367 ret = IOERR_ABORTED;
369 break;
371 default:
372 ret = IOERR_NOCMD;
373 break;
375 } else {
376 /* deaf mode */
377 ret = IOERR_ABORTED;
379 } else {
380 switch(ioreq->IOSer.io_Command)
382 case NSCMD_DEVICEQUERY:
383 ret = cmdNSDeviceQuery((struct IOStdReq *) ioreq, ncp, base);
384 break;
386 default:
387 ret = IOERR_NOCMD;
388 break;
392 if(ret != RC_DONTREPLY)
394 KPRINTF(1, ("TermIO\n"));
395 if (ret != RC_OK)
397 /* Set error codes
399 ioreq->IOSer.io_Error = ret & 0xff;
401 /* Terminate the iorequest
403 TermIO(ioreq, base);
406 AROS_LIBFUNC_EXIT
409 AROS_LH1(LONG, devAbortIO,
410 AROS_LHA(struct IOExtSer *, ioreq, A1),
411 DEVBASETYPEPTR, base, 6, dev)
413 AROS_LIBFUNC_INIT
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)
422 return(0);
425 /* Is it pending?
427 Forbid();
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);
438 Permit();
439 return(0);
441 iocmp = (struct IOExtSer *) ncp->ncp_ReadQueue.lh_Head;
442 while(iocmp->IOSer.io_Message.mn_Node.ln_Succ)
444 if(iocmp == ioreq)
446 Remove((struct Node *) ioreq);
447 ioreq->IOSer.io_Error = IOERR_ABORTED;
448 ReplyMsg(&ioreq->IOSer.io_Message);
449 Permit();
450 return(0);
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)
457 if(iocmp == ioreq)
459 Remove((struct Node *)ioreq);
460 ioreq->IOSer.io_Error = IOERR_ABORTED;
461 ReplyMsg(&ioreq->IOSer.io_Message);
462 Permit();
463 return(0);
465 iocmp = (struct IOExtSer *) iocmp->IOSer.io_Message.mn_Node.ln_Succ;
468 Permit();
469 return(-1);
471 AROS_LIBFUNC_EXIT
474 /* NSD stuff
477 static
478 const UWORD NSDSupported[] =
480 CMD_CLEAR, CMD_RESET,
481 CMD_FLUSH, CMD_READ,
482 CMD_WRITE, CMD_START,
483 CMD_STOP, SDCMD_QUERY,
484 SDCMD_SETPARAMS,
485 SDCMD_BREAK,
486 NSCMD_DEVICEQUERY, 0
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));
499 /* NULL ptr?
500 Enough data?
501 Valid request?
503 if((!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.
518 return RC_DONTREPLY;
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).
529 return RC_OK;
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);