Check for SYS/GL during library init. Reason is that
[AROS.git] / rom / usb / classes / stir4200 / dev.c
blob2d7c515c301e4b888d33e0f2224c5817e23b9b60
1 /* dev.c - usbstir4200.device by Chris Hodges
2 */
4 #include "debug.h"
6 #include "stir4200.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 IOIrDAReq *, 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 NepClassSTIr4200 *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->ioir_Req.io_Message.mn_Length && (ioreq->ioir_Req.io_Message.mn_Length < sizeof(struct IOIrDAReq)))
66 KPRINTF(20, ("devOpen: invalid MN_LENGTH (%ld < %ld)!\n",
67 ioreq->ioir_Req.io_Message.mn_Length, sizeof(struct IOIrDAReq)));
69 ioreq->ioir_Req.io_Error = IOERR_BADLENGTH;
70 } else {
71 /* Default to open failure. */
72 ioreq->ioir_Req.io_Error = IOERR_OPENFAIL;
74 ioreq->ioir_Req.io_Unit = NULL;
75 ncp = (struct NepClassSTIr4200 *) 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->ioir_Req.io_Error = IOERR_UNITBUSY;
83 } else {
84 ioreq->ioir_Req.io_Unit = (struct Unit *) ncp;
86 break;
88 ncp = (struct NepClassSTIr4200 *) ncp->ncp_Unit.unit_MsgPort.mp_Node.ln_Succ;
91 if(!ioreq->ioir_Req.io_Unit)
93 ioreq->ioir_Req.io_Error = IOERR_OPENFAIL;
94 KPRINTF(20, ("devOpen: could not open unit!\n"));
95 } else {
96 /* Opended ok! */
97 ioreq->ioir_Req.io_Message.mn_Node.ln_Type = NT_REPLYMSG;
98 ioreq->ioir_Req.io_Error = 0;
99 ioreq->ioir_Req.io_Unit->unit_OpenCnt++;
101 /* Allow queuing */
102 ncp->ncp_DenyRequests = FALSE;
104 return base;
108 ioreq->ioir_Req.io_Unit = (APTR) -1;
109 ioreq->ioir_Req.io_Device = (APTR) -1;
110 base->np_Library.lib_OpenCnt--;
112 return(NULL);
114 AROS_LIBFUNC_EXIT
118 AROS_LH1(BPTR, devClose,
119 AROS_LHA(struct IOIrDAReq *, ioreq, A1),
120 DEVBASETYPEPTR, base, 2, dev)
122 AROS_LIBFUNC_INIT
124 BPTR ret;
125 struct NepClassSTIr4200 *ncp = (struct NepClassSTIr4200 *) ioreq->ioir_Req.io_Unit;
127 KPRINTF(10, ("devClose ioreq: 0x%08lx base: 0x%08lx\n", ioreq, base));
129 ret = BNULL;
130 /* Try to flush the last buffer */
131 Forbid();
132 if(ncp->ncp_Unit.unit_MsgPort.mp_SigTask)
134 Signal(ncp->ncp_Unit.unit_MsgPort.mp_SigTask, 1L<<(ncp->ncp_Unit.unit_MsgPort.mp_SigBit));
136 Permit();
138 /* Allow queuing */
139 ncp->ncp_DenyRequests = FALSE;
141 ncp->ncp_Unit.unit_OpenCnt--;
142 ioreq->ioir_Req.io_Unit = (APTR) -1;
143 ioreq->ioir_Req.io_Device = (APTR) -1;
145 if(--base->np_Library.lib_OpenCnt == 0)
147 if(base->np_Library.lib_Flags & LIBF_DELEXP)
149 KPRINTF(5, ("devClose: calling expunge...\n"));
150 ret = AROS_LC1(BPTR, devExpunge,
151 AROS_LCA(DEVBASETYPEPTR, base, D0),
152 DEVBASETYPEPTR, base, 3, dev);
156 KPRINTF(5, ("devClose: lib_OpenCnt = %ld\n", base->np_Library.lib_OpenCnt));
158 return(ret);
160 AROS_LIBFUNC_EXIT
164 AROS_LH1(BPTR, devExpunge,
165 AROS_LHA(DEVBASETYPEPTR, extralh, D0),
166 DEVBASETYPEPTR, base, 3, dev)
168 AROS_LIBFUNC_INIT
170 BPTR ret;
172 KPRINTF(10, ("devExpunge base: 0x%08lx\n", base));
174 ret = BNULL;
176 if(base->np_Library.lib_OpenCnt == 0)
178 KPRINTF(5, ("devExpunge: Unloading...\n"));
180 CloseLibrary(base->np_UtilityBase);
182 ret = base->np_SegList;
184 KPRINTF(5, ("devExpunge: removing device node 0x%08lx\n",
185 &base->np_Library.lib_Node));
186 Remove(&base->np_Library.lib_Node);
188 KPRINTF(5, ("devExpunge: FreeMem()...\n"));
189 FreeMem((char *) base - base->np_Library.lib_NegSize,
190 (ULONG) (base->np_Library.lib_NegSize + base->np_Library.lib_PosSize));
192 KPRINTF(5, ("devExpunge: Unloading done! " DEVNAME " expunged!\n\n"));
194 return(ret);
196 else
198 KPRINTF(5, ("devExpunge: Could not expunge, LIBF_DELEXP set!\n"));
199 base->np_Library.lib_Flags |= LIBF_DELEXP;
202 return(BNULL);
204 AROS_LIBFUNC_EXIT
207 AROS_LH0(DEVBASETYPEPTR, devReserved,
208 DEVBASETYPEPTR, base, 4, dev)
210 AROS_LIBFUNC_INIT
211 return NULL;
212 AROS_LIBFUNC_EXIT
215 AROS_LH1(void, devBeginIO,
216 AROS_LHA(struct IOIrDAReq *, ioreq, A1),
217 DEVBASETYPEPTR, base, 5, dev)
219 AROS_LIBFUNC_INIT
221 struct NepClassSTIr4200 *ncp = (struct NepClassSTIr4200 *) ioreq->ioir_Req.io_Unit;
222 WORD ret = IOERR_NOCMD;
224 KPRINTF(1, ("devBeginIO ioreq: 0x%08lx base: 0x%08lx cmd: %lu\n", ioreq, base, ioreq->ioir_Req.io_Command));
226 ioreq->ioir_Req.io_Message.mn_Node.ln_Type = NT_MESSAGE;
227 ioreq->ioir_Req.io_Error = 0;
229 if(ioreq->ioir_Req.io_Command < NSCMD_DEVICEQUERY)
231 switch (ioreq->ioir_Req.io_Command)
233 case CMD_FLUSH:
234 case CMD_READ:
235 case CMD_WRITE:
236 case CMD_RESET:
237 case CMD_CLEAR:
238 if(!ncp->ncp_DenyRequests)
240 ioreq->ioir_Req.io_Flags &= ~IOF_QUICK;
241 ret = RC_DONTREPLY;
242 PutMsg(&ncp->ncp_Unit.unit_MsgPort, (struct Message *) ioreq);
243 } else {
244 ret = IOERR_ABORTED;
246 break;
248 case IRCMD_QUERYDEVICE:
249 ret = cmdQueryDevice(ioreq, ncp, base);
250 break;
252 default:
253 ret = IOERR_NOCMD;
254 break;
256 } else {
257 switch(ioreq->ioir_Req.io_Command)
259 case NSCMD_DEVICEQUERY:
260 ret = cmdNSDeviceQuery((struct IOStdReq *) ioreq, ncp, base);
261 break;
263 default:
264 ret = IOERR_NOCMD;
265 break;
269 if(ret != RC_DONTREPLY)
271 KPRINTF(1, ("TermIO\n"));
272 if (ret != RC_OK)
274 /* Set error codes
276 ioreq->ioir_Req.io_Error = ret & 0xff;
278 /* Terminate the iorequest
280 TermIO(ioreq, base);
283 AROS_LIBFUNC_EXIT
286 AROS_LH1(LONG, devAbortIO,
287 AROS_LHA(struct IOIrDAReq *, ioreq, A1),
288 DEVBASETYPEPTR, base, 6, dev)
290 AROS_LIBFUNC_INIT
292 struct NepClassSTIr4200 *ncp = (struct NepClassSTIr4200 *) ioreq->ioir_Req.io_Unit;
294 struct IOIrDAReq *iocmp;
296 KPRINTF(5, ("devAbortIO ioreq: 0x%08lx\n", ioreq));
298 /* Is it pending?
300 Forbid();
301 if(ioreq->ioir_Req.io_Message.mn_Node.ln_Type == NT_MESSAGE)
303 iocmp = (struct IOIrDAReq *) ncp->ncp_ReadQueue.lh_Head;
304 while(iocmp->ioir_Req.io_Message.mn_Node.ln_Succ)
306 if(iocmp == ioreq)
308 Remove((struct Node *) ioreq);
309 ioreq->ioir_Req.io_Error = IOERR_ABORTED;
310 ReplyMsg(&ioreq->ioir_Req.io_Message);
311 Permit();
312 return(0);
314 iocmp = (struct IOIrDAReq *) iocmp->ioir_Req.io_Message.mn_Node.ln_Succ;
316 iocmp = (struct IOIrDAReq *) ncp->ncp_WriteQueue.lh_Head;
317 while(iocmp->ioir_Req.io_Message.mn_Node.ln_Succ)
319 if(iocmp == ioreq)
321 Remove((struct Node *) ioreq);
322 ioreq->ioir_Req.io_Error = IOERR_ABORTED;
323 ReplyMsg(&ioreq->ioir_Req.io_Message);
324 Permit();
325 return(0);
327 iocmp = (struct IOIrDAReq *) iocmp->ioir_Req.io_Message.mn_Node.ln_Succ;
330 Permit();
331 return(-1);
333 AROS_LIBFUNC_EXIT
336 /* NSD stuff
339 static
340 const UWORD NSDSupported[] =
342 CMD_RESET, CMD_CLEAR,
343 CMD_FLUSH, CMD_READ,
344 CMD_WRITE,
345 NSCMD_DEVICEQUERY, 0
348 WORD cmdNSDeviceQuery(struct IOStdReq *ioreq,
349 struct NepClassSTIr4200 *ncp,
350 struct NepSTIrDevBase *base)
352 struct my_NSDeviceQueryResult *query;
354 query = (struct my_NSDeviceQueryResult *) ioreq->io_Data;
356 KPRINTF(10, ("NSCMD_DEVICEQUERY ioreq: 0x%08lx query: 0x%08lx\n", ioreq, query));
358 /* NULL ptr?
359 Enough data?
360 Valid request?
362 if((!query) ||
363 (ioreq->io_Length < sizeof(struct my_NSDeviceQueryResult)) ||
364 (query->DevQueryFormat != 0) ||
365 (query->SizeAvailable != 0))
367 /* Return error. This is special handling, since iorequest is only
368 guaranteed to be sizeof(struct IOIrDAReq). If we'd let our
369 devBeginIO dispatcher return the error, it would trash some
370 memory past end of the iorequest (ios2_WireError field).
372 ioreq->io_Error = IOERR_NOCMD;
373 TermIO((struct IOIrDAReq *) ioreq, base);
375 /* Don't reply, we already did.
377 return RC_DONTREPLY;
380 ioreq->io_Actual = query->SizeAvailable
381 = sizeof(struct my_NSDeviceQueryResult);
382 query->DeviceType = NSDEVTYPE_UNKNOWN;
383 query->DeviceSubType = 0;
384 query->SupportedCommands = NSDSupported;
386 /* Return success (note that this will NOT poke ios2_WireError).
388 return RC_OK;
391 /* /// "cmdQueryDevice()" */
393 *======================================================================
394 * cmdQueryDevice(ioreq, unit, base)
395 *======================================================================
397 * This is the device UHCMD_QUERYDEVICE routine.
399 * Returns information about the hardware.
403 WORD cmdQueryDevice(struct IOIrDAReq *ioreq,
404 struct NepClassSTIr4200 *ncp,
405 struct NepSTIrDevBase *base)
407 struct TagItem *taglist = (struct TagItem *) ioreq->ioir_Data;
408 struct TagItem *tag;
410 ULONG count = 0;
412 KPRINTF(10, ("IRCMD_QUERYDEVICE ioreq: 0x%08lx, taglist: 0x%08lx\n", ioreq, taglist));
414 if((tag = FindTagItem(IRA_Author, taglist)))
416 *((STRPTR *) tag->ti_Data) = "Chris Hodges";
417 count++;
419 if((tag = FindTagItem(IRA_ProductName, taglist)))
421 *((STRPTR *) tag->ti_Data) = "STIr4200 IrDA USB Interface";
422 count++;
424 if((tag = FindTagItem(IRA_Description, taglist)))
426 *((STRPTR *) tag->ti_Data) = "Interfacing device for STIr4200 IrDA sticks";
427 count++;
429 if((tag = FindTagItem(IRA_Copyright, taglist)))
431 *((STRPTR *) tag->ti_Data) = "©2005-2009 Chris Hodges";
432 count++;
434 if((tag = FindTagItem(IRA_Version, taglist)))
436 *((IPTR *) tag->ti_Data) = VERSION_NUMBER;
437 count++;
439 if((tag = FindTagItem(IRA_Revision, taglist)))
441 *((IPTR *) tag->ti_Data) = REVISION_NUMBER;
442 count++;
444 if((tag = FindTagItem(IRA_DriverVersion, taglist)))
446 *((IPTR *) tag->ti_Data) = 0x100;
447 count++;
449 if((tag = FindTagItem(IRA_SuppBaudRate, taglist)))
451 *((IPTR *) tag->ti_Data) = BRF_2400|BRF_9600|BRF_19200|BRF_38400|BRF_57600|BRF_115200|BRF_4000000;
452 count++;
454 if((tag = FindTagItem(IRA_SuppDataSize, taglist)))
456 *((IPTR *) tag->ti_Data) = 0x3f; // all sizes up to 2048
457 count++;
459 ioreq->ioir_Actual = count;
460 return RC_OK;
462 /* \\\ */
465 *===========================================================
466 * TermIO(ioreq, base)
467 *===========================================================
469 * Return completed ioreq to sender.
473 void TermIO(struct IOIrDAReq *ioreq,
474 struct NepSTIrDevBase *base)
476 ioreq->ioir_Req.io_Message.mn_Node.ln_Type = NT_FREEMSG;
478 /* If not quick I/O, reply the message
480 if(!(ioreq->ioir_Req.io_Flags & IOF_QUICK))
482 ReplyMsg(&ioreq->ioir_Req.io_Message);