2 Copyright © 1995-2006, The AROS Development Team. All rights reserved.
5 Desc: Tap Unit hidd class implementation.
9 #define __OOP_NOATTRBASES__
11 /* Some POSIX includes */
17 #include <sys/socket.h>
18 #include <sys/ioctl.h>
21 #include <linux/if_tun.h>
23 #include "unix_funcs.h"
26 /* the rest are Amiga includes */
27 #define timeval aros_timeval
28 #include <proto/exec.h>
29 #include <proto/utility.h>
30 #include <proto/oop.h>
31 #include <proto/alib.h>
32 #include <exec/libraries.h>
33 #include <exec/ports.h>
34 #include <exec/memory.h>
35 #include <exec/interrupts.h>
36 #include <exec/lists.h>
38 #include <utility/tagitem.h>
40 #include <hidd/unixio.h>
42 #include <aros/symbolsets.h>
43 #include <aros/macros.h>
46 #include LC_LIBDEFS_FILE
52 #include <aros/debug.h>
54 void tapunit_receive_data();
55 void tapunit_write_more_data();
57 #define MAX(a,b) (((a) > (b))?(a):(b))
58 #define MIN(a,b) (((a) > (b))?(b):(a))
61 #include "tap_intern.h"
64 static char * unitname
[] =
71 /*************************** Classes *****************************/
73 static OOP_AttrBase HiddTapUnitAB
;
75 static struct OOP_ABDescr attrbases
[] =
77 { IID_Hidd_TapUnit
, &HiddTapUnitAB
},
81 /******* TapUnit::New() ***********************************/
82 OOP_Object
*UXTapUnit__Root__New(OOP_Class
*cl
, OOP_Object
*obj
, struct pRoot_New
*msg
)
84 struct HIDDTapUnitData
* data
;
85 static const struct TagItem tags
[] = {{ TAG_END
, 0}};
86 struct TagItem
*tag
, *tstate
;
89 EnterFunc(bug("TapUnit::New()\n"));
91 tstate
= msg
->attrList
;
92 while ((tag
= NextTagItem((const struct TagItem
**)&tstate
))) {
95 if (IS_HIDDTAPUNIT_ATTR(tag
->ti_Tag
, idx
)) {
97 case aoHidd_TapUnit_Unit
:
98 unitnum
= (ULONG
)tag
->ti_Data
;
103 } /* while (tags to process) */
105 D(bug("!!!!Request for unit number %d\n",unitnum
));
107 obj
= (OOP_Object
*)OOP_DoSuperMethod(cl
, obj
, (OOP_Msg
)msg
);
110 data
= OOP_INST_DATA(cl
, obj
);
112 data
->unitnum
= unitnum
;
114 D(bug("Creating network device %s.\n",unitname
[data
->unitnum
]));
116 data
->filedescriptor
= unix_open_nonblock("/dev/net/tun");
117 if (data
->filedescriptor
< 0)
118 data
->filedescriptor
= unix_open_nonblock("/dev/tap");
120 D(bug("Opened %s on handle %d\n",unitname
[data
->unitnum
], data
->filedescriptor
));
122 if (-1 != data
->filedescriptor
) {
124 memset(&ifr
, 0, sizeof(ifr
));
125 ifr
.ifr_flags
= IFF_TAP
| IFF_NO_PI
;
126 strncpy(ifr
.ifr_name
, unitname
[data
->unitnum
], IFNAMSIZ
);
129 ** Configure the tty driver ?!?!?!
132 data
->replyport_read
= AllocMem(sizeof(struct MsgPort
), MEMF_PUBLIC
|MEMF_CLEAR
);
133 data
->replyport_write
= AllocMem(sizeof(struct MsgPort
), MEMF_PUBLIC
|MEMF_CLEAR
);
135 if (data
->replyport_read
&& data
->replyport_write
) {
137 ** Init the msg ports. They don't need a signal to be allocated
139 NEWLIST(&data
->replyport_read
->mp_MsgList
);
140 data
->replyport_read
->mp_Node
.ln_Type
= NT_MSGPORT
;
142 NEWLIST(&data
->replyport_write
->mp_MsgList
);
143 data
->replyport_write
->mp_Node
.ln_Type
= NT_MSGPORT
;
145 data
->softint_read
= AllocMem(sizeof(struct Interrupt
), MEMF_CLEAR
);
146 data
->softint_write
= AllocMem(sizeof(struct Interrupt
), MEMF_CLEAR
);
148 if (data
->softint_read
&& data
->softint_write
) {
149 data
->softint_read
->is_Data
= data
;
150 data
->softint_read
->is_Code
= tapunit_receive_data
;
152 data
->softint_write
->is_Data
= data
;
153 data
->softint_write
->is_Code
= tapunit_write_more_data
;
155 data
->replyport_read
->mp_Flags
= PA_SOFTINT
;
156 data
->replyport_read
->mp_SoftInt
= data
->softint_read
;
158 data
->replyport_write
->mp_Flags
= PA_SOFTINT
;
159 data
->replyport_write
->mp_SoftInt
= data
->softint_write
;
161 data
->unixio_read
= OOP_NewObject(NULL
, CLID_Hidd_UnixIO
, (struct TagItem
*)tags
);
162 data
->unixio_write
= OOP_NewObject(NULL
, CLID_Hidd_UnixIO
, (struct TagItem
*)tags
);
164 if (NULL
!= data
->unixio_read
&& NULL
!= data
->unixio_write
)
166 Hidd_UnixIO_IOControlFile(data
->unixio_read
,
167 data
->filedescriptor
,
173 D(bug("Creating UnixIO AsyncIO command!\n"));
175 error
= Hidd_UnixIO_AsyncIO(data
->unixio_read
,
176 data
->filedescriptor
,
177 vHidd_UnixIO_Terminal
,
178 data
->replyport_read
,
179 vHidd_UnixIO_Read
| vHidd_UnixIO_Keep
,
182 error
= Hidd_UnixIO_AsyncIO(data
->unixio_write
,
183 data
->filedescriptor
,
184 vHidd_UnixIO_Terminal
,
185 data
->replyport_write
,
186 vHidd_UnixIO_Write
| vHidd_UnixIO_Keep
,
192 if (NULL
!= data
->unixio_read
)
193 OOP_DisposeObject(data
->unixio_read
);
195 if (NULL
!= data
->unixio_write
)
196 OOP_DisposeObject(data
->unixio_write
);
199 if (data
->softint_read
)
200 FreeMem(data
->softint_read
, sizeof(struct Interrupt
));
201 if (data
->softint_write
)
202 FreeMem(data
->softint_write
, sizeof(struct Interrupt
));
205 if (data
->replyport_read
)
206 FreeMem(data
->replyport_read
, sizeof(struct MsgPort
));
207 if (data
->replyport_write
)
208 FreeMem(data
->replyport_write
, sizeof(struct MsgPort
));
212 close(data
->filedescriptor
);
215 OOP_DisposeObject(obj
);
219 D(bug("%s - an error occurred!\n",__FUNCTION__
));
222 ReturnPtr("TapUnit::New()", OOP_Object
*, obj
);
225 /******* TapUnit::Dispose() ***********************************/
226 OOP_Object
*UXTapUnit__Root__Dispose(OOP_Class
*cl
, OOP_Object
*obj
, OOP_Msg msg
)
228 struct HIDDTapUnitData
* data
;
229 EnterFunc(bug("TapUnit::Dispose()\n"));
231 data
= OOP_INST_DATA(cl
, obj
);
232 D(bug("Freeing filedescriptor (%d)!\n",data
->filedescriptor
));
234 if (-1 != data
->filedescriptor
) {
235 Hidd_UnixIO_AbortAsyncIO(data
->unixio_read
,
236 data
->filedescriptor
,
239 close(data
->filedescriptor
);
241 FreeMem(data
->replyport_read
, sizeof(struct MsgPort
));
242 FreeMem(data
->replyport_write
, sizeof(struct MsgPort
));
244 FreeMem(data
->softint_read
, sizeof(struct Interrupt
));
245 FreeMem(data
->softint_write
, sizeof(struct Interrupt
));
247 OOP_DisposeObject(data
->unixio_read
);
248 OOP_DisposeObject(data
->unixio_write
);
250 OOP_DoSuperMethod(cl
, obj
, (OOP_Msg
)msg
);
251 ReturnPtr("TapUnit::Dispose()", OOP_Object
*, obj
);
256 /******* TapUnit::Init() **********************************/
257 BOOL
UXTapUnit__Hidd_TapUnit__Init(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_TapUnit_Init
*msg
)
259 struct HIDDTapUnitData
* data
= OOP_INST_DATA(cl
, o
);
261 EnterFunc(bug("TapUnit::Init()\n"));
262 data
->DataReceivedCallBack
= msg
->DataReceived
;
263 data
->DataReceivedUserData
= msg
->DataReceivedUserData
;
264 data
->DataWriteCallBack
= msg
->WriteData
;
265 data
->DataWriteUserData
= msg
->WriteDataUserData
;
267 ReturnBool("TapUnit::Init()", TRUE
);
270 /******* TapUnit::Write() **********************************/
271 ULONG
UXTapUnit__Hidd_TapUnit__Write(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_TapUnit_Write
*msg
)
273 struct HIDDTapUnitData
* data
= OOP_INST_DATA(cl
, o
);
276 EnterFunc(bug("TapUnit::Write()\n"));
278 if (TRUE
== data
->stopped
)
281 D(bug("Writing %d bytes to fd %d. The stream is:",
283 data
->filedescriptor
));
286 UBYTE
*ptr
= msg
->Outbuffer
;
289 for (j
=0; j
< MIN(64,msg
->Length
); j
++)
293 bug(" %02x", ptr
[j
]);
298 len
= write(data
->filedescriptor
,
303 ReturnInt("TapUnit::Write()",ULONG
, len
);
306 /******* TapUnit::Start() **********************************/
307 VOID
UXTapUnit__Hidd_TapUnit__Start(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_TapUnit_Start
*msg
)
309 struct HIDDTapUnitData
* data
= OOP_INST_DATA(cl
, o
);
312 * Allow or start feeding the UART with data. Get the data
315 if (TRUE
== data
->stopped
) {
316 if (NULL
!= data
->DataWriteCallBack
)
317 data
->DataWriteCallBack(data
->unitnum
, data
->DataWriteUserData
);
319 * Also mark the stopped flag as FALSE.
321 data
->stopped
= FALSE
;
325 /******* TapUnit::Stop() **********************************/
326 VOID
UXTapUnit__Hidd_TapUnit__Stop(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_TapUnit_Stop
*msg
)
328 struct HIDDTapUnitData
* data
= OOP_INST_DATA(cl
, o
);
331 * The next time the interrupt comes along and asks for
332 * more data we just don't do anything...
334 data
->stopped
= TRUE
;
337 /****** TapUnit::GetStatus ********************************/
338 UWORD
UXTapUnit__Hidd_TapUnit__GetStatus(OOP_Class
*cl
, OOP_Object
*o
, struct pHidd_TapUnit_GetStatus
*msg
)
341 struct HIDDTapUnitData
* data
= OOP_INST_DATA(cl
, o
);
348 /************* The software interrupt handler that gets data from PORT *****/
351 #define READBUFFER_SIZE 2048
353 AROS_UFH3(void, tapunit_receive_data
,
354 AROS_UFHA(APTR
, iD
, A1
),
355 AROS_UFHA(APTR
, iC
, A5
),
356 AROS_UFHA(struct ExecBase
*, SysBase
, A6
))
360 struct HIDDTapUnitData
* data
= iD
;
362 UBYTE buffer
[READBUFFER_SIZE
];
365 ** Read the data from the port ...
367 len
= read(data
->filedescriptor
, buffer
, READBUFFER_SIZE
);
369 ** ... and deliver them to whoever is interested.
374 bug("Got %d bytes from the port.", len
);
376 for (j
=0; j
< MIN(64,len
); j
++)
380 bug(" %02x", buffer
[j
]);
385 if (NULL
!= data
->DataReceivedCallBack
)
386 data
->DataReceivedCallBack(buffer
, len
, data
->unitnum
, data
->DataReceivedUserData
);
391 AROS_UFH3(void, tapunit_write_more_data
,
392 AROS_UFHA(APTR
, iD
, A1
),
393 AROS_UFHA(APTR
, iC
, A5
),
394 AROS_UFHA(struct ExecBase
*, SysBase
, A6
))
398 struct HIDDTapUnitData
* data
= iD
;
399 // struct Message * msg;
402 ** Ask for more data be written to the unit
404 D(bug("Asking for more data to be written to unit %d\n",data
->unitnum
));
406 if (NULL
!= data
->DataWriteCallBack
)
407 data
->DataWriteCallBack(data
->unitnum
, data
->DataWriteUserData
);
413 /******* init_tapunitclass ********************************/
415 static int UXTapUnit_InitAttrBases(LIBBASETYPEPTR LIBBASE
)
417 return OOP_ObtainAttrBases(attrbases
);
421 static int UXTapUnit_ExpungeAttrBases(LIBBASETYPEPTR LIBBASE
)
423 OOP_ReleaseAttrBases(attrbases
);
427 ADD2INITLIB(UXTapUnit_InitAttrBases
, 0)
428 ADD2EXPUNGELIB(UXTapUnit_ExpungeAttrBases
, 0)