added concrete implementations of putc(), getc(), getchar() and gets()
[tangerine.git] / arch / all-unix / hidd / tap / TapUnitClass.c
blob529269a46f6bfe74250f062da7101028ce71337e
1 /*
2 Copyright © 1995-2006, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Tap Unit hidd class implementation.
6 Lang: english
7 */
9 #define __OOP_NOATTRBASES__
11 /* Some POSIX includes */
12 #include <stdio.h>
13 #include <termios.h>
14 #include <unistd.h>
16 #include <sys/uio.h>
17 #include <sys/socket.h>
18 #include <sys/ioctl.h>
20 #include <linux/if.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>
39 #include <hidd/tap.h>
40 #include <hidd/unixio.h>
42 #include <aros/symbolsets.h>
43 #include <aros/macros.h>
46 #include LC_LIBDEFS_FILE
48 #undef SDEBUG
49 #undef DEBUG
50 #define SDEBUG 1
51 #define DEBUG 1
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"
62 #undef timeval
64 static char * unitname[] =
66 "aros0",
67 "aros1",
68 "aros2"
71 /*************************** Classes *****************************/
73 static OOP_AttrBase HiddTapUnitAB;
75 static struct OOP_ABDescr attrbases[] =
77 { IID_Hidd_TapUnit, &HiddTapUnitAB },
78 { NULL, NULL }
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;
87 ULONG unitnum = 0;
89 EnterFunc(bug("TapUnit::New()\n"));
91 tstate = msg->attrList;
92 while ((tag = NextTagItem((const struct TagItem **)&tstate))) {
93 ULONG idx;
95 if (IS_HIDDTAPUNIT_ATTR(tag->ti_Tag, idx)) {
96 switch (idx) {
97 case aoHidd_TapUnit_Unit:
98 unitnum = (ULONG)tag->ti_Data;
99 break;
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);
109 if (obj) {
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) {
123 struct ifreq ifr;
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,
168 TUNSETIFF,
169 &ifr,
170 NULL);
172 ULONG error;
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,
180 SysBase);
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,
187 SysBase);
188 goto exit;
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);
216 obj = NULL;
217 } /* if (obj) */
219 D(bug("%s - an error occurred!\n",__FUNCTION__));
221 exit:
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,
237 SysBase);
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);
274 ULONG len = 0;
276 EnterFunc(bug("TapUnit::Write()\n"));
278 if (TRUE == data->stopped)
279 return 0;
281 D(bug("Writing %d bytes to fd %d. The stream is:",
282 msg->Length,
283 data->filedescriptor));
286 UBYTE *ptr = msg->Outbuffer;
287 int j;
289 for (j=0; j < MIN(64,msg->Length); j++)
291 if ((j%16) == 0)
292 bug("\n%03x:", j);
293 bug(" %02x", ptr[j]);
295 bug("\n");
298 len = write(data->filedescriptor,
299 msg->Outbuffer,
300 msg->Length);
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
313 * from upper layer.
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)
340 #if 0
341 struct HIDDTapUnitData * data = OOP_INST_DATA(cl, o);
342 #endif
344 return 0;
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))
358 AROS_USERFUNC_INIT
360 struct HIDDTapUnitData * data = iD;
361 ssize_t len;
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.
373 int j;
374 bug("Got %d bytes from the port.", len);
376 for (j=0; j < MIN(64,len); j++)
378 if ((j%16) == 0)
379 bug("\n%03x:", j);
380 bug(" %02x", buffer[j]);
382 bug("\n");
385 if (NULL != data->DataReceivedCallBack)
386 data->DataReceivedCallBack(buffer, len, data->unitnum, data->DataReceivedUserData);
388 AROS_USERFUNC_EXIT
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))
396 AROS_USERFUNC_INIT
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);
409 AROS_USERFUNC_EXIT
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);
424 return TRUE;
427 ADD2INITLIB(UXTapUnit_InitAttrBases, 0)
428 ADD2EXPUNGELIB(UXTapUnit_ExpungeAttrBases, 0)