1 /* dev.c - usbstir4200.device by Chris Hodges
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
))
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 IOIrDAReq
*, ioreq
, A1
),
48 AROS_LHA(ULONG
, unit
, D0
),
49 AROS_LHA(ULONG
, flags
, D1
),
50 DEVBASETYPEPTR
, base
, 1, dev
)
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
;
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
;
84 ioreq
->ioir_Req
.io_Unit
= (struct Unit
*) ncp
;
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"));
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
++;
102 ncp
->ncp_DenyRequests
= FALSE
;
108 ioreq
->ioir_Req
.io_Unit
= (APTR
) -1;
109 ioreq
->ioir_Req
.io_Device
= (APTR
) -1;
110 base
->np_Library
.lib_OpenCnt
--;
118 AROS_LH1(BPTR
, devClose
,
119 AROS_LHA(struct IOIrDAReq
*, ioreq
, A1
),
120 DEVBASETYPEPTR
, base
, 2, dev
)
125 struct NepClassSTIr4200
*ncp
= (struct NepClassSTIr4200
*) ioreq
->ioir_Req
.io_Unit
;
127 KPRINTF(10, ("devClose ioreq: 0x%08lx base: 0x%08lx\n", ioreq
, base
));
130 /* Try to flush the last buffer */
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
));
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
));
164 AROS_LH1(BPTR
, devExpunge
,
165 AROS_LHA(DEVBASETYPEPTR
, extralh
, D0
),
166 DEVBASETYPEPTR
, base
, 3, dev
)
172 KPRINTF(10, ("devExpunge base: 0x%08lx\n", base
));
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"));
198 KPRINTF(5, ("devExpunge: Could not expunge, LIBF_DELEXP set!\n"));
199 base
->np_Library
.lib_Flags
|= LIBF_DELEXP
;
207 AROS_LH0(DEVBASETYPEPTR
, devReserved
,
208 DEVBASETYPEPTR
, base
, 4, dev
)
215 AROS_LH1(void, devBeginIO
,
216 AROS_LHA(struct IOIrDAReq
*, ioreq
, A1
),
217 DEVBASETYPEPTR
, base
, 5, dev
)
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
)
238 if(!ncp
->ncp_DenyRequests
)
240 ioreq
->ioir_Req
.io_Flags
&= ~IOF_QUICK
;
242 PutMsg(&ncp
->ncp_Unit
.unit_MsgPort
, (struct Message
*) ioreq
);
248 case IRCMD_QUERYDEVICE
:
249 ret
= cmdQueryDevice(ioreq
, ncp
, base
);
257 switch(ioreq
->ioir_Req
.io_Command
)
259 case NSCMD_DEVICEQUERY
:
260 ret
= cmdNSDeviceQuery((struct IOStdReq
*) ioreq
, ncp
, base
);
269 if(ret
!= RC_DONTREPLY
)
271 KPRINTF(1, ("TermIO\n"));
276 ioreq
->ioir_Req
.io_Error
= ret
& 0xff;
278 /* Terminate the iorequest
286 AROS_LH1(LONG
, devAbortIO
,
287 AROS_LHA(struct IOIrDAReq
*, ioreq
, A1
),
288 DEVBASETYPEPTR
, base
, 6, dev
)
292 struct NepClassSTIr4200
*ncp
= (struct NepClassSTIr4200
*) ioreq
->ioir_Req
.io_Unit
;
294 struct IOIrDAReq
*iocmp
;
296 KPRINTF(5, ("devAbortIO ioreq: 0x%08lx\n", ioreq
));
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
)
308 Remove((struct Node
*) ioreq
);
309 ioreq
->ioir_Req
.io_Error
= IOERR_ABORTED
;
310 ReplyMsg(&ioreq
->ioir_Req
.io_Message
);
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
)
321 Remove((struct Node
*) ioreq
);
322 ioreq
->ioir_Req
.io_Error
= IOERR_ABORTED
;
323 ReplyMsg(&ioreq
->ioir_Req
.io_Message
);
327 iocmp
= (struct IOIrDAReq
*) iocmp
->ioir_Req
.io_Message
.mn_Node
.ln_Succ
;
340 const UWORD NSDSupported
[] =
342 CMD_RESET
, CMD_CLEAR
,
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
));
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.
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).
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
;
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";
419 if((tag
= FindTagItem(IRA_ProductName
, taglist
)))
421 *((STRPTR
*) tag
->ti_Data
) = "STIr4200 IrDA USB Interface";
424 if((tag
= FindTagItem(IRA_Description
, taglist
)))
426 *((STRPTR
*) tag
->ti_Data
) = "Interfacing device for STIr4200 IrDA sticks";
429 if((tag
= FindTagItem(IRA_Copyright
, taglist
)))
431 *((STRPTR
*) tag
->ti_Data
) = "©2005-2009 Chris Hodges";
434 if((tag
= FindTagItem(IRA_Version
, taglist
)))
436 *((IPTR
*) tag
->ti_Data
) = VERSION_NUMBER
;
439 if((tag
= FindTagItem(IRA_Revision
, taglist
)))
441 *((IPTR
*) tag
->ti_Data
) = REVISION_NUMBER
;
444 if((tag
= FindTagItem(IRA_DriverVersion
, taglist
)))
446 *((IPTR
*) tag
->ti_Data
) = 0x100;
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
;
454 if((tag
= FindTagItem(IRA_SuppDataSize
, taglist
)))
456 *((IPTR
*) tag
->ti_Data
) = 0x3f; // all sizes up to 2048
459 ioreq
->ioir_Actual
= count
;
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
);