1 /* dev.c - usbmodem.device by Chris Hodges
6 #include "cdcacm.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
&& ncp
->ncp_Task
)
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
)
93 ioreq
->IOSer
.io_Error
= IOERR_OPENFAIL
;
94 KPRINTF(20, ("devOpen: could not open unit!\n"));
97 ioreq
->IOSer
.io_Message
.mn_Node
.ln_Type
= NT_REPLYMSG
;
98 ioreq
->IOSer
.io_Error
= 0;
99 ioreq
->IOSer
.io_Unit
->unit_OpenCnt
++;
101 ioreq
->io_CtlChar
= SER_DEFAULT_CTLCHAR
;
102 ioreq
->io_RBufLen
= DEFREADBUFLEN
;
103 ioreq
->io_ExtFlags
= 0;
104 ioreq
->io_Baud
= 9600;
105 ioreq
->io_BrkTime
= 250000;
106 ioreq
->io_TermArray
.TermArray0
= 0;
107 ioreq
->io_TermArray
.TermArray1
= 0;
108 ioreq
->io_ReadLen
= 8;
109 ioreq
->io_WriteLen
= 8;
110 ioreq
->io_StopBits
= 1;
111 if(ioreq
->io_SerFlags
& SERF_RAD_BOOGIE
)
113 ioreq
->io_SerFlags
|= SERF_XDISABLED
;
114 ioreq
->io_SerFlags
&= ~SERF_PARTY_ON
|SERF_PARTY_ODD
;
118 ncp
->ncp_DenyRequests
= FALSE
;
120 /* initial settings */
121 ioreq
->IOSer
.io_Command
= SDCMD_SETPARAMS
;
122 ioreq
->IOSer
.io_Flags
&= ~IOF_QUICK
;
123 PutMsg(&ncp
->ncp_Unit
.unit_MsgPort
, (struct Message
*) ioreq
);
124 while(!GetMsg(&ncp
->ncp_Unit
.unit_MsgPort
))
126 WaitPort(&ncp
->ncp_Unit
.unit_MsgPort
);
132 ioreq
->IOSer
.io_Unit
= (APTR
) -1;
133 ioreq
->IOSer
.io_Device
= (APTR
) -1;
134 base
->np_Library
.lib_OpenCnt
--;
142 AROS_LH1(BPTR
, devClose
,
143 AROS_LHA(struct IOExtSer
*, ioreq
, A1
),
144 DEVBASETYPEPTR
, base
, 2, dev
)
149 struct NepClassSerial
*ncp
= (struct NepClassSerial
*) ioreq
->IOSer
.io_Unit
;
151 KPRINTF(10, ("devClose ioreq: 0x%08lx base: 0x%08lx\n", ioreq
, base
));
155 /* Don't allow queuing */
156 ncp
->ncp_DenyRequests
= TRUE
;
158 ncp
->ncp_Unit
.unit_OpenCnt
--;
159 ioreq
->IOSer
.io_Unit
= (APTR
) -1;
160 ioreq
->IOSer
.io_Device
= (APTR
) -1;
162 if(--base
->np_Library
.lib_OpenCnt
== 0)
164 if(base
->np_Library
.lib_Flags
& LIBF_DELEXP
)
166 KPRINTF(5, ("devClose: calling expunge...\n"));
167 ret
= AROS_LC1(BPTR
, devExpunge
,
168 AROS_LCA(DEVBASETYPEPTR
, base
, D0
),
169 DEVBASETYPEPTR
, base
, 3, dev
);
173 KPRINTF(5, ("devClose: lib_OpenCnt = %ld\n", base
->np_Library
.lib_OpenCnt
));
181 AROS_LH1(BPTR
, devExpunge
,
182 AROS_LHA(DEVBASETYPEPTR
, extralh
, D0
),
183 DEVBASETYPEPTR
, base
, 3, dev
)
189 KPRINTF(10, ("devExpunge base: 0x%08lx\n", base
));
193 if(base
->np_Library
.lib_OpenCnt
== 0)
195 KPRINTF(5, ("devExpunge: Unloading...\n"));
197 CloseLibrary(base
->np_UtilityBase
);
199 ret
= base
->np_SegList
;
201 KPRINTF(5, ("devExpunge: removing device node 0x%08lx\n",
202 &base
->np_Library
.lib_Node
));
203 Remove(&base
->np_Library
.lib_Node
);
205 KPRINTF(5, ("devExpunge: FreeMem()...\n"));
206 FreeMem((char *) base
- base
->np_Library
.lib_NegSize
,
207 (ULONG
) (base
->np_Library
.lib_NegSize
+ base
->np_Library
.lib_PosSize
));
209 KPRINTF(5, ("devExpunge: Unloading done! " DEVNAME
" expunged!\n\n"));
215 KPRINTF(5, ("devExpunge: Could not expunge, LIBF_DELEXP set!\n"));
216 base
->np_Library
.lib_Flags
|= LIBF_DELEXP
;
224 AROS_LH0(DEVBASETYPEPTR
, devReserved
,
225 DEVBASETYPEPTR
, base
, 4, dev
)
232 AROS_LH1(void, devBeginIO
,
233 AROS_LHA(struct IOExtSer
*, ioreq
, A1
),
234 DEVBASETYPEPTR
, base
, 5, dev
)
238 struct NepClassSerial
*ncp
= (struct NepClassSerial
*) ioreq
->IOSer
.io_Unit
;
239 WORD ret
= IOERR_NOCMD
;
241 KPRINTF(1, ("devBeginIO ioreq: 0x%08lx base: 0x%08lx cmd: %lu len: %ld\n", ioreq
, base
, ioreq
->IOSer
.io_Command
, ioreq
->IOSer
.io_Length
));
243 ioreq
->IOSer
.io_Message
.mn_Node
.ln_Type
= NT_MESSAGE
;
244 ioreq
->IOSer
.io_Error
= 0;
246 if(ioreq
->IOSer
.io_Command
< NSCMD_DEVICEQUERY
)
248 switch (ioreq
->IOSer
.io_Command
)
251 if(ncp
->ncp_EPInStream
&& (!ncp
->ncp_DenyRequests
))
253 ioreq
->IOSer
.io_Flags
&= ~IOF_QUICK
;
255 AddTail(&ncp
->ncp_ReadQueue
, &ioreq
->IOSer
.io_Message
.mn_Node
);
258 Signal(ncp
->ncp_Task
, 1UL<<ncp
->ncp_TaskMsgPort
->mp_SigBit
);
268 if(!ncp
->ncp_DenyRequests
)
270 if(ioreq
->IOSer
.io_Length
== -1)
272 ioreq
->IOSer
.io_Length
= strlen(ioreq
->IOSer
.io_Data
);
274 ioreq
->IOSer
.io_Flags
&= ~IOF_QUICK
;
276 AddTail(&ncp
->ncp_WriteQueue
, &ioreq
->IOSer
.io_Message
.mn_Node
);
279 Signal(ncp
->ncp_Task
, 1UL<<ncp
->ncp_TaskMsgPort
->mp_SigBit
);
289 ncp
->ncp_DevSuspend
= FALSE
;
294 ncp
->ncp_DevSuspend
= TRUE
;
302 case SDCMD_SETPARAMS
:
304 if(!ncp
->ncp_DenyRequests
)
306 ioreq
->IOSer
.io_Flags
&= ~IOF_QUICK
;
308 PutMsg(&ncp
->ncp_Unit
.unit_MsgPort
, (struct Message
*) ioreq
);
310 ioreq
->IOSer
.io_Actual
= 0;
320 switch(ioreq
->IOSer
.io_Command
)
322 case NSCMD_DEVICEQUERY
:
323 ret
= cmdNSDeviceQuery((struct IOStdReq
*) ioreq
, ncp
, base
);
332 if(ret
!= RC_DONTREPLY
)
334 KPRINTF(1, ("TermIO\n"));
339 ioreq
->IOSer
.io_Error
= ret
& 0xff;
341 /* Terminate the iorequest
349 AROS_LH1(LONG
, devAbortIO
,
350 AROS_LHA(struct IOExtSer
*, ioreq
, A1
),
351 DEVBASETYPEPTR
, base
, 6, dev
)
355 struct NepClassSerial
*ncp
= (struct NepClassSerial
*) ioreq
->IOSer
.io_Unit
;
357 struct IOExtSer
*iocmp
;
359 KPRINTF(5, ("devAbortIO ioreq: 0x%08lx\n", ioreq
));
364 if(ioreq
->IOSer
.io_Message
.mn_Node
.ln_Type
== NT_MESSAGE
)
366 /* check if it's the writing pipe */
367 if(ioreq
== ncp
->ncp_WritePending
)
369 if(ncp
->ncp_AbortSignal
>= 0)
371 /* prod the subtask */
372 Signal(ncp
->ncp_Task
, 1UL<<ncp
->ncp_AbortSignal
);
377 iocmp
= (struct IOExtSer
*) ncp
->ncp_ReadQueue
.lh_Head
;
378 while(iocmp
->IOSer
.io_Message
.mn_Node
.ln_Succ
)
382 Remove((struct Node
*) ioreq
);
383 ioreq
->IOSer
.io_Error
= IOERR_ABORTED
;
384 ReplyMsg(&ioreq
->IOSer
.io_Message
);
388 iocmp
= (struct IOExtSer
*) iocmp
->IOSer
.io_Message
.mn_Node
.ln_Succ
;
390 iocmp
= (struct IOExtSer
*) ncp
->ncp_WriteQueue
.lh_Head
;
391 while(iocmp
->IOSer
.io_Message
.mn_Node
.ln_Succ
)
395 Remove((struct Node
*)ioreq
);
396 ioreq
->IOSer
.io_Error
= IOERR_ABORTED
;
397 ReplyMsg(&ioreq
->IOSer
.io_Message
);
401 iocmp
= (struct IOExtSer
*) iocmp
->IOSer
.io_Message
.mn_Node
.ln_Succ
;
414 const UWORD NSDSupported
[] =
416 CMD_CLEAR
, CMD_RESET
,
418 CMD_WRITE
, CMD_START
,
419 CMD_STOP
, SDCMD_QUERY
,
425 WORD
cmdNSDeviceQuery(struct IOStdReq
*ioreq
,
426 struct NepClassSerial
*ncp
,
427 struct NepSerDevBase
*base
)
429 struct my_NSDeviceQueryResult
*query
;
431 query
= (struct my_NSDeviceQueryResult
*) ioreq
->io_Data
;
433 KPRINTF(10, ("NSCMD_DEVICEQUERY ioreq: 0x%08lx query: 0x%08lx\n", ioreq
, query
));
440 (ioreq
->io_Length
< sizeof(struct my_NSDeviceQueryResult
)) ||
441 (query
->DevQueryFormat
!= 0) ||
442 (query
->SizeAvailable
!= 0))
444 /* Return error. This is special handling, since iorequest is only
445 guaranteed to be sizeof(struct IOStdReq). If we'd let our
446 devBeginIO dispatcher return the error, it would trash some
447 memory past end of the iorequest (ios2_WireError field).
449 ioreq
->io_Error
= IOERR_NOCMD
;
450 TermIO((struct IOExtSer
*) ioreq
, base
);
452 /* Don't reply, we already did.
457 ioreq
->io_Actual
= query
->SizeAvailable
458 = sizeof(struct my_NSDeviceQueryResult
);
459 query
->DeviceType
= NSDEVTYPE_SERIAL
;
460 query
->DeviceSubType
= 0;
461 query
->SupportedCommands
= NSDSupported
;
463 /* Return success (note that this will NOT poke ios2_WireError).
469 *===========================================================
470 * TermIO(ioreq, base)
471 *===========================================================
473 * Return completed ioreq to sender.
477 void TermIO(struct IOExtSer
*ioreq
,
478 struct NepSerDevBase
*base
)
480 ioreq
->IOSer
.io_Message
.mn_Node
.ln_Type
= NT_FREEMSG
;
482 /* If not quick I/O, reply the message
484 if(!(ioreq
->IOSer
.io_Flags
& IOF_QUICK
))
486 ReplyMsg(&ioreq
->IOSer
.io_Message
);