Fixed binary search: no more infinite loops when vendor is unknown.
[tangerine.git] / arch / .unmaintained / generic / hidd / parallel / ParallelUnitClass.c
blob0970161aadf1f4b2b545b8f245fddccc981b2570
1 /*
2 Copyright © 1995-2001, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Parallel Unit hidd class implementation.
6 Lang: english
7 */
9 /*
10 * This is the SerialUnitClass as used for Linux. You will have to
11 * modify this code here and make it work with the hardware that
12 * you want to write the hidd for.
13 * I hope the Linux code inside the methods helps a little bit
14 * in explaining what needs to be done inside each method.
19 /* Some POSIX includes */
20 #include <sys/types.h>
21 #include <sys/stat.h>
22 #include <fcntl.h>
23 #include <stdio.h>
24 #include <termios.h>
25 #include <unistd.h>
29 /* the rest are Amiga includes */
30 #include <proto/exec.h>
31 #include <proto/utility.h>
32 #include <proto/oop.h>
33 #include <proto/alib.h>
34 #include <exec/libraries.h>
35 #include <exec/ports.h>
36 #include <exec/memory.h>
37 #include <exec/interrupts.h>
38 #include <exec/lists.h>
40 #include <utility/tagitem.h>
41 #include <hidd/parallel.h>
42 #include <hidd/unixio.h>
44 #include "parallel_intern.h"
46 #undef SDEBUG
47 #undef DEBUG
48 #define SDEBUG 1
49 #define DEBUG 1
50 #include <aros/debug.h>
52 void parallelunit_receive_data();
53 void parallelunit_write_more_data();
55 char * unitname[] =
57 "/dev/lp0",
58 "/dev/lp1",
59 "/dev/lp2"
62 /*************************** Classes *****************************/
64 static OOP_AttrBase HiddParallelUnitAB;
66 static struct OOP_ABDescr attrbases[] =
68 { IID_Hidd_ParallelUnit, &HiddParallelUnitAB },
69 { NULL, NULL }
72 /******* ParallelUnit::New() ***********************************/
73 static OOP_Object *parallelunit_new(OOP_Class *cl, OOP_Object *obj, struct pRoot_New *msg)
75 struct HIDDParallelUnitData * data;
76 static const struct TagItem tags[] = {{ TAG_END, 0}};
77 struct TagItem *tag, *tstate;
78 ULONG unitnum = 0;
80 EnterFunc(bug("ParallelUnit::New()\n"));
82 tstate = msg->attrList;
83 while ((tag = NextTagItem((const struct TagItem **)&tstate)))
85 ULONG idx;
87 if (IS_HIDDPARALLELUNIT_ATTR(tag->ti_Tag, idx))
89 switch (idx)
91 case aoHidd_ParallelUnit_Unit:
92 unitnum = (ULONG)tag->ti_Data;
93 break;
97 } /* while (tags to process) */
99 D(bug("!!!!Request for unit number %d\n",unitnum));
101 obj = (OOP_Object *)OOP_DoSuperMethod(cl, obj, (OOP_Msg)msg);
103 if (obj)
105 data = OOP_INST_DATA(cl, obj);
107 data->unitnum = unitnum;
109 D(bug("Opening %s.\n",unitname[data->unitnum]));
111 data->filedescriptor = open(unitname[data->unitnum], O_NONBLOCK|O_RDWR);
113 D(bug("Opened %s on handle %d\n",unitname[data->unitnum], data->filedescriptor));
115 if (-1 != data->filedescriptor)
118 ** Configure the tty driver ??!?!?!
121 data->replyport_read = AllocMem(sizeof(struct MsgPort), MEMF_PUBLIC|MEMF_CLEAR);
122 data->replyport_write= AllocMem(sizeof(struct MsgPort), MEMF_PUBLIC|MEMF_CLEAR);
124 if (data->replyport_read && data->replyport_write)
127 ** Init the msg ports. They don't need a signal to be allocated
129 NEWLIST(&data->replyport_read->mp_MsgList);
130 data->replyport_read ->mp_Node.ln_Type = NT_MSGPORT;
132 NEWLIST(&data->replyport_write->mp_MsgList);
133 data->replyport_write->mp_Node.ln_Type = NT_MSGPORT;
135 data->softint_read = AllocMem(sizeof(struct Interrupt), MEMF_CLEAR);
136 data->softint_write = AllocMem(sizeof(struct Interrupt), MEMF_CLEAR);
138 if (data->softint_read && data->softint_write)
140 data->softint_read->is_Data = data;
141 data->softint_read->is_Code = parallelunit_receive_data;
143 data->softint_write->is_Data = data;
144 data->softint_write->is_Code = parallelunit_write_more_data;
146 data->replyport_read->mp_Flags = PA_SOFTINT;
147 data->replyport_read->mp_SoftInt = data->softint_read;
149 data->replyport_write->mp_Flags = PA_SOFTINT;
150 data->replyport_write->mp_SoftInt = data->softint_write;
152 data->unixio_read = OOP_NewObject(NULL, CLID_Hidd_UnixIO, (struct TagItem *)tags);
153 data->unixio_write = OOP_NewObject(NULL, CLID_Hidd_UnixIO, (struct TagItem *)tags);
155 if (NULL != data->unixio_read && NULL != data->unixio_write)
157 ULONG error;
158 D(bug("Creating UnixIO AsyncIO command!\n"));
160 error = Hidd_UnixIO_AsyncIO(data->unixio_read,
161 data->filedescriptor,
162 data->replyport_read,
163 vHidd_UnixIO_Read);
164 goto exit;
168 if (NULL != data->unixio_read)
169 OOP_DisposeObject(data->unixio_read);
171 if (NULL != data->unixio_write)
172 OOP_DisposeObject(data->unixio_write);
175 if (data->softint_read)
176 FreeMem(data->softint_read, sizeof(struct Interrupt));
177 if (data->softint_write)
178 FreeMem(data->softint_write, sizeof(struct Interrupt));
181 if (data->replyport_read)
182 FreeMem(data->replyport_read , sizeof(struct MsgPort));
183 if (data->replyport_write)
184 FreeMem(data->replyport_write, sizeof(struct MsgPort));
188 close(data->filedescriptor);
191 OOP_DisposeObject(obj);
192 obj = NULL;
193 } /* if (obj) */
195 D(bug("%s - an error occurred!\n",__FUNCTION__));
197 exit:
198 ReturnPtr("ParallelUnit::New()", OOP_Object *, obj);
201 /******* ParallelUnit::Dispose() ***********************************/
202 static OOP_Object *parallelunit_dispose(OOP_Class *cl, OOP_Object *obj, OOP_Msg msg)
204 struct HIDDParallelUnitData * data;
205 EnterFunc(bug("ParallelUnit::Dispose()\n"));
207 data = OOP_INST_DATA(cl, obj);
208 D(bug("Freeing filedescriptor (%d)!\n",data->filedescriptor));
210 if (-1 != data->filedescriptor)
212 Hidd_UnixIO_AbortAsyncIO(data->unixio_read,
213 data->filedescriptor);
214 // Hidd_UnixIO_AbortAsyncIONotification(data->unixio_write,
215 // data->filedescriptor);
217 close(data->filedescriptor);
219 FreeMem(data->replyport_read, sizeof(struct MsgPort));
220 FreeMem(data->replyport_write, sizeof(struct MsgPort));
222 FreeMem(data->softint_read , sizeof(struct Interrupt));
223 FreeMem(data->softint_write, sizeof(struct Interrupt));
225 OOP_DisposeObject(data->unixio_read);
226 OOP_DisposeObject(data->unixio_write);
228 OOP_DoSuperMethod(cl, obj, (OOP_Msg)msg);
229 ReturnPtr("ParallelUnit::Dispose()", OOP_Object *, obj);
234 /******* ParallelUnit::Init() **********************************/
235 BOOL parallelunit_init(OOP_Class *cl, OOP_Object *o, struct pHidd_ParallelUnit_Init *msg)
237 struct HIDDParallelUnitData * data = OOP_INST_DATA(cl, o);
239 EnterFunc(bug("ParallelUnit::Init()\n"));
240 data->DataReceivedCallBack = msg->DataReceived;
241 data->DataReceivedUserData = msg->DataReceivedUserData;
242 data->DataWriteCallBack = msg->WriteData;
243 data->DataWriteUserData = msg->WriteDataUserData;
245 ReturnBool("ParallelUnit::Init()", TRUE);
248 /******* ParallelUnit::Write() **********************************/
249 ULONG parallelunit_write(OOP_Class *cl, OOP_Object *o, struct pHidd_ParallelUnit_Write *msg)
251 struct HIDDParallelUnitData * data = OOP_INST_DATA(cl, o);
252 ULONG len = 0;
253 ULONG error;
255 EnterFunc(bug("ParallelUnit::Write()\n"));
257 D(bug("Writing %d bytes to fd %d (stream: %s)\n",
258 msg->Length,
259 data->filedescriptor,
260 msg->Outbuffer));
262 len = write(data->filedescriptor,
263 msg->Outbuffer,
264 msg->Length);
266 if (len < msg->Length)
269 // !!!!!! FROM WHAT I CAN TELL THE FOLLOWING LINE
270 // CAUSES PROBLEMS. IT IS NECESSARY TO HAVE IT, THOUGH.
271 error = Hidd_UnixIO_AsyncIO(data->unixio_write,
272 data->filedescriptor,
273 data->replyport_write,
274 vHidd_UnixIO_Write);
278 ReturnInt("ParallelUnit::Write()",ULONG, len);
281 /************* The software interrupt handler that gets data from PORT *****/
284 #undef OOPBase
285 #undef SysBase
286 #undef UtilityBase
288 #define READBUFFER_SIZE 513
290 AROS_UFH3(void, parallelunit_receive_data,
291 AROS_UFHA(APTR, iD, A1),
292 AROS_UFHA(APTR, iC, A5),
293 AROS_UFHA(struct ExecBase *, SysBase, A6))
295 ULONG error;
296 struct HIDDParallelUnitData * data = iD;
297 ssize_t len;
298 UBYTE buffer[READBUFFER_SIZE];
299 struct Message * msg;
302 ** Get the unixio message from my port and free it
304 msg = GetMsg(data->replyport_read);
305 FreeMem(msg, sizeof(struct uioMessage));
308 ** Read the data from the port ...
310 len = read(data->filedescriptor, buffer, READBUFFER_SIZE);
312 ** ... and deliver them to whoever is interested.
315 if (NULL != data->DataReceivedCallBack)
316 data->DataReceivedCallBack(buffer, len, data->unitnum, data->DataReceivedUserData);
319 ** I want to be notified when the next data are coming in.
321 error = Hidd_UnixIO_AsyncIO(data->unixio_read,
322 data->filedescriptor,
323 data->replyport_read,
324 vHidd_UnixIO_Read);
328 AROS_UFH3(void, parallelunit_write_more_data,
329 AROS_UFHA(APTR, iD, A1),
330 AROS_UFHA(APTR, iC, A5),
331 AROS_UFHA(struct ExecBase *, SysBase, A6))
333 struct HIDDParallelUnitData * data = iD;
334 struct Message * msg;
337 ** Get the unixio message from my port and free it
339 msg = GetMsg(data->replyport_read);
340 FreeMem(msg, sizeof(struct uioMessage));
343 ** Ask for more data be written to the unit
345 D(bug("Asking for more data to be written to unit %d\n",data->unitnum));
347 if (NULL != data->DataWriteCallBack)
348 data->DataWriteCallBack(data->unitnum, data->DataWriteUserData);
352 /******* init_parallelunitclass ********************************/
354 #define SysBase (csd->sysbase)
355 #define OOPBase (csd->oopbase)
356 #define UtilityBase (csd->utilitybase)
359 #define NUM_ROOT_METHODS 2
360 #define NUM_PARALLELUNIT_METHODS 2
362 OOP_Class *init_parallelunitclass (struct class_static_data *csd)
364 OOP_Class *cl = NULL;
366 struct OOP_MethodDescr parallelunithiddroot_descr[NUM_ROOT_METHODS + 1] =
368 {(IPTR (*)())parallelunit_new, moRoot_New},
369 {(IPTR (*)())parallelunit_dispose, moRoot_Dispose},
371 {(IPTR (*)())parallelunit_set, moRoot_Set},
372 {(IPTR (*)())parallelunit_get, moRoot_Get},
374 {NULL, 0UL}
377 struct OOP_MethodDescr parallelunithidd_descr[NUM_PARALLELUNIT_METHODS + 1] =
379 {(IPTR (*)())parallelunit_init, moHidd_ParallelUnit_Init},
380 {(IPTR (*)())parallelunit_write, moHidd_ParallelUnit_Write},
381 {NULL, 0UL}
384 struct OOP_InterfaceDescr ifdescr[] =
386 {parallelunithiddroot_descr , IID_Root , NUM_ROOT_METHODS},
387 {parallelunithidd_descr , IID_Hidd_ParallelUnit , NUM_PARALLELUNIT_METHODS},
388 {NULL, NULL, 0}
391 OOP_AttrBase MetaAttrBase = OOP_GetAttrBase(IID_Meta);
393 struct TagItem tags[] =
395 { aMeta_SuperID, (IPTR)CLID_Root},
396 { aMeta_InterfaceDescr, (IPTR)ifdescr},
397 { aMeta_ID, (IPTR)CLID_Hidd_ParallelUnit},
398 { aMeta_InstSize, (IPTR)sizeof (struct HIDDParallelUnitData) },
399 {TAG_DONE, 0UL}
403 EnterFunc(bug(" init_parallelunitclass(csd=%p)\n", csd));
405 cl = OOP_NewObject(NULL, CLID_HiddMeta, tags);
406 D(bug("Class=%p\n", cl));
407 if(cl)
409 if (OOP_ObtainAttrBases(attrbases))
411 D(bug("ParallelUnit Class ok\n"));
412 cl->UserData = (APTR)csd;
414 OOP_AddClass(cl);
415 } else {
416 free_parallelunitclass(csd);
417 cl = NULL;
421 ReturnPtr("init_parallelunitclass", OOP_Class *, cl);
425 void free_parallelunitclass(struct class_static_data *csd)
427 EnterFunc(bug("free_parallelhiddclass(csd=%p)\n", csd));
429 if(csd)
431 OOP_RemoveClass(csd->parallelhiddclass);
433 if(csd->parallelhiddclass) OOP_DisposeObject((OOP_Object *) csd->parallelhiddclass);
434 csd->parallelhiddclass = NULL;
437 ReturnVoid("free_parallelhiddclass");