1 /*
2 * Copyright (c) 2001 Tommy Bohlin <tommy@gatespace.com>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26 /* unix.c
27 */
28
29 #include <irda.h>
30
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <errno.h>
35 #include <stdarg.h>
36 #include <syslog.h>
37 #include <sys/types.h>
38 #include <sys/ioctl.h>
39 #include <sys/time.h>
40 #include <unistd.h>
41 #include <fcntl.h>
42 #include <termios.h>
43
44 /**********************************************************************
45 * Constants
46 **********************************************************************/
47
48 #ifdef IRDA_KERNEL_DRIVER
49
50 static const char id_kernel_framedevice[]="kernel frame device";
51 static const char id_kfdev_inbuffer[]="kernel frame device in buffer";
52 static const char id_kfdev_outbuffer[]="kernel frame device out buffer";
53
54 static const char* defaultKernelPort = "/dev/irframe0";
55
56 #endif /* IRDA_KERNEL_DRIVER */
57
58 /**********************************************************************
59 * Data structures
60 **********************************************************************/
61
62 typedef struct Memory {
63 struct Memory* next;
64 const char* id;
65 void* ptr;
66 int size;
67 } Memory;
68
69 typedef struct Timer {
70 struct Timer* next;
71 struct timeval expire;
72 void (*func)(void*);
73 void* handle;
74 } Timer;
75
76 typedef struct Source {
77 struct Source* next;
78 int fd;
79 void (*func)(void* handle);
80 void* handle;
81 } Source;
82
83 typedef struct UNIXSerialPort {
84 SerialPort serial;
85 struct UNIXSerialPort* next;
86 int speedMask;
87 int fd;
88 u_char inBuf[1024];
89 int inHead;
90 int inFree;
91 int stopped;
92 u_char outBuf[1024];
93 int outFree;
94 } UNIXSerialPort;
95
96 #ifdef IRDA_KERNEL_DRIVER
97
98 typedef struct KernelFrameDevice {
99 FrameDevice frame;
100 char *devname;
101 int fdesc;
102 u_char* inBuf;
103 u_char* outBuf;
104 int maxSize;
105 int maxOutSize;
106 int maxspeed;
107 } KernelFrameDevice;
108
109 #endif /* IRDA_KERNEL_DRIVER */
110
111 /**********************************************************************
112 * State
113 **********************************************************************/
114
115 int evtDebug;
116
117 static bool sysLog=FALSE;
118 static FILE* logFile=NULL;
119
120 static Source* sources;
121 static UNIXSerialPort* ports;
122 static Timer* timers;
123 static Memory* allocs;
124
125 /**********************************************************************
126 * Support functions
127 **********************************************************************/
128
addTime(struct timeval * t,int ms)129 static void addTime(struct timeval* t, int ms)
130 {
131 t->tv_sec+=ms/1000;
132 t->tv_usec+=1000*(ms%1000);
133 if(t->tv_usec<0) {
134 t->tv_sec-=1;
135 t->tv_usec+=1000000;
136 } else if(t->tv_usec>=1000000) {
137 t->tv_sec+=1;
138 t->tv_usec-=1000000;
139 }
140 }
141
cmpTime(const struct timeval * t1,const struct timeval * t2)142 static int cmpTime(const struct timeval* t1, const struct timeval* t2)
143 {
144 long t=t1->tv_sec-t2->tv_sec;
145 return t ? t : t1->tv_usec-t2->tv_usec;
146 }
147
unlinkTimer(void (* func)(void * handle),void * handle)148 static Timer* unlinkTimer(void (*func)(void* handle), void* handle)
149 {
150 Timer** th=&timers;
151 Timer* t;
152
153 while((t=*th)) {
154 if(t->func==func && t->handle==handle) {
155 *th=t->next;
156 return t;
157 }
158 th=&t->next;
159 }
160 return 0;
161 }
162
linkTimer(Timer * e)163 static void linkTimer(Timer* e) {
164 Timer** th=&timers;
165 Timer* t;
166
167 while((t=*th)) {
168 if(cmpTime(&e->expire,&t->expire)<0) break;
169 th=&t->next;
170 }
171 e->next=*th;
172 *th=e;
173 }
174
evtRemoveSource(int fd)175 void evtRemoveSource(int fd)
176 {
177 Source** sh=&sources;
178 Source* s;
179
180 while((s=*sh)) {
181 if(s->fd==fd) {
182 *sh=s->next;
183 free(s);
184 break;
185 }
186 sh=&s->next;
187 }
188 }
189
evtAddSource(int fd,void (* func)(void * handle),void * handle)190 void evtAddSource(int fd, void (*func)(void* handle), void* handle)
191 {
192 Source* s;
193
194 evtRemoveSource(fd);
195
196 s=malloc(sizeof(Source));
197 s->fd=fd;
198 s->func=func;
199 s->handle=handle;
200 s->next=sources;
201 sources=s;
202 }
203
204 /**********************************************************************
205 * Serial I/O
206 **********************************************************************/
207
serialSetSpeed(SerialPort * sp,int speed)208 static void serialSetSpeed(SerialPort* sp, int speed) {
209 UNIXSerialPort* usp=(UNIXSerialPort*)sp;
210 struct termios t;
211 int speedcode;
212
213 if(tcgetattr(usp->fd,&t)) {
214 birda_log("tcgetattr failed\n");
215 return;
216 }
217 switch(speed) {
218 case 115200: speedcode=B115200; break;
219 case 57600: speedcode=B57600; break;
220 case 38400: speedcode=B38400; break;
221 case 19200: speedcode=B19200; break;
222 case 9600: speedcode=B9600; break;
223 case 2400: speedcode=B2400; break;
224 default:
225 birda_log("unsupported speed\n");
226 return;
227 }
228 cfsetispeed(&t,speedcode);
229 cfsetospeed(&t,speedcode);
230 if(tcsetattr(usp->fd,TCSADRAIN,&t)) {
231 birda_log("tcsetattr failed\n");
232 }
233 }
234
serialSetLine(SerialPort * sp,int line)235 static void serialSetLine(SerialPort* sp, int line) {
236 UNIXSerialPort* usp=(UNIXSerialPort*)sp;
237 int flags;
238
239 if(ioctl(usp->fd,TIOCMGET,&flags)==-1) {
240 birda_log("ioctl failed %d\n", __LINE__);
241 }
242
243 flags&=~(TIOCM_DTR|TIOCM_RTS);
244 if(line&LINE_DTR) flags|=TIOCM_DTR;
245 if(line&LINE_RTS) flags|=TIOCM_RTS;
246
247 if(ioctl(usp->fd,TIOCMSET,&flags)==-1) {
248 birda_log("ioctl failed %d\n", __LINE__);
249 }
250 }
251
serialGetSpeedMask(SerialPort * sp)252 static int serialGetSpeedMask(SerialPort* sp)
253 {
254 UNIXSerialPort* usp=(UNIXSerialPort*)sp;
255
256 return usp->speedMask;
257 }
258
serialInput(void * sp)259 static void serialInput(void* sp)
260 {
261 UNIXSerialPort* usp=(UNIXSerialPort*)sp;
262 int empty;
263
264 int k=usp->inHead<=usp->inFree ?
265 sizeof usp->inBuf-usp->inFree : usp->inHead-usp->inFree-1;
266 int n=read(usp->fd,usp->inBuf+usp->inFree,k);
267
268 if(usp->serial.debug&SP_DEBUG_INPUT) birda_log("serial port read %d bytes\n",n);
269 if(n<=0) return;
270 empty=usp->inHead==usp->inFree;
271 usp->inFree=(usp->inFree+n)%sizeof usp->inBuf;
272 if(((usp->inFree+1)%sizeof usp->inBuf)==usp->inHead) {
273 usp->stopped=1;
274 evtRemoveSource(usp->fd);
275 }
276 if(empty && usp->serial.status)
277 usp->serial.status(&usp->serial, SERIAL_INPUT_AVAILABLE);
278 }
279
serialGetChar(SerialPort * sp)280 static int serialGetChar(SerialPort* sp)
281 {
282 UNIXSerialPort* usp=(UNIXSerialPort*)sp;
283 int c;
284 int nchars=usp->inFree-usp->inHead;
285 if(nchars<0) nchars+=sizeof usp->inBuf;
286
287 if(nchars==0) {
288 usp->inHead=usp->inFree=0;
289 return SERIAL_INBUF_EMPTY;
290 }
291 if(usp->stopped && nchars<sizeof usp->inBuf/4) {
292 usp->stopped=0;
293 evtAddSource(usp->fd,serialInput,usp);
294 }
295 c=usp->inBuf[usp->inHead];
296 usp->inHead=(usp->inHead+1)%sizeof usp->inBuf;
297 return c;
298 }
299
flush(UNIXSerialPort * usp)300 static void flush(UNIXSerialPort* usp)
301 {
302 int n=usp->outFree;
303 int k=0;
304 while(k<n) {
305 int i=write(usp->fd,usp->outBuf+k,n-k);
306 if(i>0) k+=i;
307 else if(i==0 || (errno!=EAGAIN && errno!=EINTR)) break;
308 }
309 usp->outFree=0;
310 }
311
serialOutput(void * sp)312 static void serialOutput(void* sp)
313 {
314 UNIXSerialPort* usp=(UNIXSerialPort*)sp;
315 if(evtDebug&EVT_DEBUG_TIMERS) birda_log("serialOutput\n");
316 if(usp->outFree>0) flush(usp);
317 }
318
serialPutChar(SerialPort * sp,int c)319 static void serialPutChar(SerialPort* sp, int c)
320 {
321 UNIXSerialPort* usp=(UNIXSerialPort*)sp;
322
323 usp->outBuf[usp->outFree++]=c;
324 if(usp->outFree==sizeof usp->outBuf) flush(usp);
325 else evtSetTimer(0,serialOutput,usp);
326 }
327
serialClose(SerialPort * sp)328 static void serialClose(SerialPort* sp)
329 {
330 UNIXSerialPort* usp=(UNIXSerialPort*)sp;
331 UNIXSerialPort** uh=&ports;
332 UNIXSerialPort* u;
333
334 while((u=*uh)) {
335 if(u==usp) {
336 *uh=u->next;
337 break;
338 } else {
339 uh=&u->next;
340 }
341 }
342 if(!u) {
343 birda_log("ERROR: closing unallocated UNIX serial port\n");
344 return;
345 }
346
347 evtCancelTimer(serialOutput,usp);
348 evtRemoveSource(usp->fd);
349 free(usp);
350 }
351
352 /**********************************************************************
353 * External interface
354 **********************************************************************/
355
setFileLog(const char * file)356 bool setFileLog(const char* file)
357 {
358 FILE* f=fopen(file,"a");
359
360 if(!f) return FALSE;
361 logFile=f;
362 return TRUE;
363 }
364
setSysLog(void)365 void setSysLog(void)
366 {
367 sysLog=TRUE;
368 }
369
birda_log(const char * fmt,...)370 void birda_log(const char* fmt, ...)
371 {
372 va_list ap;
373
374 va_start(ap,fmt);
375 if(sysLog) {
376 vsyslog(LOG_INFO,fmt,ap);
377 } else {
378 if(!logFile) logFile=stderr;
379 vfprintf(logFile,fmt,ap);
380 fflush(logFile);
381 }
382 va_end(ap);
383 }
384
allocMem(const char * id,int size)385 void* allocMem(const char* id, int size)
386 {
387 void* ptr=malloc(size);
388 Memory* m=malloc(sizeof(Memory));
389
390 if(!ptr || !m) {
391 birda_log("PANIC: malloc failed\n");
392 return 0;
393 }
394
395 m->ptr=ptr;
396 m->id=id;
397 m->size=size;
398 m->next=allocs;
399 allocs=m;
400
401 return ptr;
402 }
403
growMem(void * ptr,int size)404 void* growMem(void* ptr, int size)
405 {
406 Memory* m=allocs;
407 void* nptr;
408
409 while(m && m->ptr!=ptr) m=m->next;
410 if(!m) {
411 birda_log("ERROR: growing unallocated memory\n");
412 return 0;
413 }
414
415 nptr=realloc(ptr,size);
416 if(!nptr) {
417 birda_log("PANIC: realloc failed\n");
418 return 0;
419 }
420
421 m->ptr=nptr;
422 m->size=size;
423
424 return nptr;
425 }
426
freeMem(void * ptr)427 void freeMem(void *ptr)
428 {
429 Memory** mh=&allocs;
430 Memory* m;
431
432 while((m=*mh)) {
433 if(m->ptr==ptr) {
434 *mh=m->next;
435 free(m);
436 free(ptr);
437 return;
438 } else {
439 mh=&m->next;
440 }
441 }
442 birda_log("ERROR: freeing unallocated memory\n");
443 }
444
showResources(void)445 void showResources(void)
446 {
447 int n,b;
448 Source* s;
449 UNIXSerialPort* u;
450 Timer* t;
451 Memory* m;
452
453 birda_log("-----------------\n");
454
455 for(n=0,u=ports;u;u=u->next) n++;
456 birda_log("%d unixSerialPorts\n",n);
457
458 for(n=0,s=sources;s;s=s->next) if(s->func!=serialInput) n++;
459 birda_log("%d other sources\n",n);
460
461 for(n=0,t=timers;t;t=t->next) n++;
462 birda_log("%d timers\n",n);
463
464 birda_log("Memory:\n");
465 for(n=0,b=0,m=allocs;m;m=m->next) {
466 birda_log(" addr=%p size=%5d id=%s\n",m->ptr,m->size,m->id);
467 n++;
468 b+=m->size;
469 }
470 birda_log(" total: %d blocks, %d bytes\n",n,b);
471 birda_log("-----------------\n");
472 }
473
getRandom(unsigned max)474 unsigned getRandom(unsigned max)
475 {
476 static bool inited=FALSE;
477 unsigned mask;
478
479 if(max==0) return 0;
480
481 if(!inited) {
482 struct timeval t;
483 gettimeofday(&t,0);
484 srandom(t.tv_sec^t.tv_usec);
485 inited=TRUE;
486 }
487
488 for(mask=1;mask<max;) mask=(mask<<1)|1;
489 for(;;) {
490 int val=random()&mask;
491 if(mask&0x80000000) val^=random()<<1;
492 if(val<=max) return val;
493 }
494 }
495
createSerialPort(const char * dev,int maxspeed)496 SerialPort* createSerialPort(const char* dev, int maxspeed)
497 {
498 int fd;
499 struct termios t;
500 UNIXSerialPort* usp;
501 int speedMask=
502 SPEED_2400|SPEED_9600|SPEED_19200|SPEED_38400|SPEED_57600|SPEED_115200;
503
504 if(maxspeed>0) {
505 if(maxspeed<115200) speedMask&=~SPEED_115200;
506 if(maxspeed< 57600) speedMask&=~SPEED_57600;
507 if(maxspeed< 38400) speedMask&=~SPEED_38400;
508 if(maxspeed< 19200) speedMask&=~SPEED_19200;
509 if(maxspeed< 9600) return 0;
510 }
511
512 if((fd=open(dev,O_RDWR|O_NOCTTY|O_NONBLOCK))<0) return 0;
513
514 t.c_iflag=0;
515 t.c_oflag=0;
516 t.c_cflag=CREAD|CS8|CLOCAL;
517 t.c_lflag=0;
518 t.c_cc[VMIN]=1;
519 t.c_cc[VTIME]=0;
520
521 cfsetispeed(&t,B9600);
522 cfsetospeed(&t,B9600);
523 if(tcsetattr(fd,TCSANOW,&t) || fcntl(fd,F_SETFL,0)==-1) {
524 close(fd);
525 return 0;
526 }
527
528 usp=malloc(sizeof(UNIXSerialPort));
529 usp->serial.close=serialClose;
530 usp->serial.setSpeed=serialSetSpeed;
531 usp->serial.setLine=serialSetLine;
532 usp->serial.getSpeedMask=serialGetSpeedMask;
533 usp->serial.getChar=serialGetChar;
534 usp->serial.putChar=serialPutChar;
535 usp->serial.debug=0;
536 usp->serial.handle=0;
537 usp->serial.status=0;
538 usp->speedMask=speedMask;
539 usp->fd=fd;
540
541 usp->inHead=usp->inFree=0;
542 usp->outFree=0;
543 evtAddSource(usp->fd,serialInput,usp);
544
545 usp->next=ports;
546 ports=usp;
547
548 return &usp->serial;
549 }
550
evtCancelTimer(void (* func)(void *),void * handle)551 void evtCancelTimer(void (*func)(void*), void* handle)
552 {
553 Timer* t=unlinkTimer(func,handle);
554 if(t) free(t);
555 }
556
evtSetTimer(int delay,void (* func)(void *),void * handle)557 void evtSetTimer(int delay, void (*func)(void*), void* handle)
558 {
559 Timer* t=unlinkTimer(func,handle);
560 if(!t) {
561 t=malloc(sizeof(Timer));
562 t->func=func;
563 t->handle=handle;
564 }
565 gettimeofday(&t->expire,0);
566 addTime(&t->expire,delay);
567 linkTimer(t);
568 }
569
evtLoop(void)570 void evtLoop(void)
571 {
572 while(timers || sources) {
573 int fdmax;
574 fd_set fds;
575 struct timeval t;
576 Source* s;
577
578 if(timers) {
579 gettimeofday(&t,0);
580 t.tv_sec=timers->expire.tv_sec-t.tv_sec;
581 t.tv_usec=timers->expire.tv_usec-t.tv_usec;
582 if(t.tv_usec<0) {
583 t.tv_sec-=1;
584 t.tv_usec+=1000000;
585 }
586 if(t.tv_sec<0) {
587 Timer* ti=timers;
588 timers=ti->next;
589 if(evtDebug&EVT_DEBUG_TIMERS)
590 birda_log("timer called %p %p\n",ti->func,ti->handle);
591 ti->func(ti->handle);
592 if(evtDebug&EVT_DEBUG_TIMERS) birda_log("timer completed\n");
593 free(ti);
594 continue;
595 }
596 }
597
598 fdmax=0;
599 FD_ZERO(&fds);
600 for(s=sources;s;s=s->next) {
601 FD_SET(s->fd,&fds);
602 if(fdmax<=s->fd) fdmax=s->fd+1;
603 }
604
605 if(evtDebug&EVT_DEBUG_SELECT)
606 birda_log("select %s timers\n",timers ? "with" : "without");
607
608 if(select(fdmax,&fds,0,0,timers ? &t : 0)==-1 && errno!=EINTR)
609 perror("select");
610
611 if(evtDebug&EVT_DEBUG_SELECT)
612 birda_log("wakeup\n");
613
614 for(s=sources;s && !FD_ISSET(s->fd,&fds);s=s->next);
615 if(s) s->func(s->handle);
616 }
617 }
618
619 /**********************************************************************
620 * Kernel frame device support
621 **********************************************************************/
622
623 #ifdef IRDA_KERNEL_DRIVER
624
kfd_close(FrameDevice * fd)625 static void kfd_close(FrameDevice* fd)
626 {
627 KernelFrameDevice* kfd = (KernelFrameDevice*)fd;
628 evtRemoveSource(kfd->fdesc);
629 close(kfd->fdesc);
630 freeMem(kfd);
631 }
632
kfd_setParams(FrameDevice * fd,int baud,int ebofs,int maxSize)633 static int kfd_setParams(FrameDevice* fd, int baud, int ebofs, int maxSize)
634 {
635 KernelFrameDevice* kfd = (KernelFrameDevice*)fd;
636 struct irda_params params;
637 params.speed = baud;
638 params.ebofs = ebofs;
639 params.maxsize = maxSize;
640
641 if (ioctl(kfd->fdesc, IRDA_SET_PARAMS, ¶ms) == -1) {
642 birda_log("ioctl failed %d\n", __LINE__);
643 }
644
645 if(kfd->maxSize != maxSize) {
646 kfd->maxSize = maxSize;
647 if (kfd->inBuf)
648 freeMem(kfd->inBuf);
649 kfd->inBuf = kfd->maxSize ? allocMem(id_kfdev_inbuffer, maxSize+2) : 0;
650 }
651
652 return 0;
653 }
654
kfd_resetParams(FrameDevice * fd)655 static void kfd_resetParams(FrameDevice* fd)
656 {
657 KernelFrameDevice* kfd = (KernelFrameDevice*)fd;
658
659 if (ioctl(kfd->fdesc, IRDA_RESET_PARAMS) == -1) {
660 birda_log("ioctl failed %d\n", __LINE__);
661 }
662 }
663
kfd_sendFrame(FrameDevice * fd,const void * buf0,int len)664 static void kfd_sendFrame(FrameDevice* fd, const void* buf0, int len)
665 {
666 KernelFrameDevice* kfd = (KernelFrameDevice*)fd;
667 #if 0
668 len = createSIRFrame(kfd->ebofs, buf0, len, kfd->outBuf, kfd->maxOutSize);
669 write(kfd->fdesc, kfd->outBuf, len);
670 #else
671 write(kfd->fdesc, buf0, len);
672 #endif
673 }
674
kfd_getSpeedMask(FrameDevice * fd)675 static int kfd_getSpeedMask(FrameDevice* fd)
676 {
677 KernelFrameDevice* kfd = (KernelFrameDevice*)fd;
678 int maxspeed = kfd->maxspeed;
679 int speedmask;
680
681 if (ioctl(kfd->fdesc, IRDA_GET_SPEEDMASK, &speedmask) == -1) {
682 birda_log("ioctl failed %d\n", __LINE__);
683 }
684
685 if(maxspeed>0) {
686 if(maxspeed<16000000) speedmask&=~SPEED_16000000;
687 if(maxspeed<4000000) speedmask&=~SPEED_4000000;
688 if(maxspeed<1152000) speedmask&=~SPEED_1152000;
689 if(maxspeed<576000) speedmask&=~SPEED_576000;
690 if(maxspeed<115200) speedmask&=~SPEED_115200;
691 if(maxspeed< 57600) speedmask&=~SPEED_57600;
692 if(maxspeed< 38400) speedmask&=~SPEED_38400;
693 if(maxspeed< 19200) speedmask&=~SPEED_19200;
694 if(maxspeed< 9600) speedmask&=~SPEED_9600;
695 }
696 return speedmask;
697 }
698
kfd_getMinTurnaroundMask(FrameDevice * fd)699 static int kfd_getMinTurnaroundMask(FrameDevice* fd)
700 {
701 KernelFrameDevice* kfd = (KernelFrameDevice*)fd;
702 int tamask;
703
704 if (ioctl(kfd->fdesc, IRDA_GET_TURNAROUNDMASK, &tamask) == -1) {
705 birda_log("ioctl failed %d\n", __LINE__);
706 }
707
708 return tamask;
709 }
710
kfd_readFrame(void * handle)711 static void kfd_readFrame(void *handle)
712 {
713 KernelFrameDevice* kfd = (KernelFrameDevice*)handle;
714 ssize_t len = read(kfd->fdesc, kfd->inBuf, (ssize_t)kfd->maxSize);
715 if (len < 0) {
716 perror("kfd_read");
717 }
718 if (len > 0) { /* Must be? */
719 if (kfd->frame.frame)
720 kfd->frame.frame(&kfd->frame, kfd->inBuf, len); /* dev driver skip ck */
721 }
722 }
723
createKernelFrameDevice(char * dev,int maxspeed)724 FrameDevice* createKernelFrameDevice(char *dev, int maxspeed)
725 {
726 KernelFrameDevice *kfd =
727 allocMem(id_kernel_framedevice, sizeof(KernelFrameDevice));
728
729 if (!dev) {
730 dev = (char *)defaultKernelPort;
731 }
732 kfd->devname = dev;
733 kfd->maxSize = 4096;
734 kfd->maxspeed = maxspeed;
735
736 if ((kfd->fdesc = open(kfd->devname, O_RDWR|O_NONBLOCK)) < 0) {
737 freeMem(kfd);
738 birda_log("Cannot open port %s\n", dev);
739 exit(-16);
740 }
741
742 kfd->frame.close = kfd_close;
743 kfd->frame.setParams = kfd_setParams;
744 kfd->frame.resetParams = kfd_resetParams;
745 kfd->frame.sendFrame = kfd_sendFrame;
746 kfd->frame.getSpeedMask = kfd_getSpeedMask;
747 kfd->frame.getMinTurnaroundMask = kfd_getMinTurnaroundMask;
748 kfd->frame.debug = 0;
749 kfd->frame.handle = 0;
750 kfd->frame.frame = 0;
751
752 kfd->maxOutSize = 8192;
753 kfd->inBuf = allocMem(id_kfdev_inbuffer, kfd->maxSize+2);
754 kfd->outBuf = allocMem(id_kfdev_outbuffer, kfd->maxOutSize);
755
756 evtAddSource(kfd->fdesc, kfd_readFrame, kfd);
757
758 return &kfd->frame;
759 }
760
761 #endif /* IRDA_KERNEL_DRIVER */
762