source: titan/titan/fb.h @ 44347

Last change on this file since 44347 was 44347, checked in by gost, 3 years ago

next test vu Boxen

File size: 16.3 KB
Line 
1#ifndef FB_H
2#define FB_H
3
4#ifdef CONFIG_ION
5#define ION_HEAP_TYPE_BMEM      (ION_HEAP_TYPE_CUSTOM + 1)
6#define ION_HEAP_ID_MASK        (1 << ION_HEAP_TYPE_BMEM)
7#define ACCEL_MEM_SIZE          (32*1024*1024)
8int m_accel_fd;
9#endif
10
11
12
13
14struct fb* getfb(char *name)
15{
16        struct fb *node = fb;
17
18        while(node != NULL)
19        {
20                if(ostrstr(node->name, name) != NULL)
21                        return node;
22
23                node = node->next;
24        }
25        debug(444, "framebuffer not found (%s)", name);
26        return NULL;
27}
28
29long getfbsize(int dev)
30{
31        struct fb* node = fb;
32        unsigned long fbmemcount = 0;
33        struct fb_fix_screeninfo fix_screeninfo;
34
35        if(fb == NULL)
36        {
37                err("NULL dedect");
38                return 0;
39        }
40
41#ifndef NOFB
42        if(ioctl(fb->fd, FBIOGET_FSCREENINFO, &fix_screeninfo) == -1)
43        {
44                perr("ioctl FBIOGET_FSCREENINFO failed");
45                return 0;
46        }
47#else
48        fix_screeninfo.smem_len = 16*1024*1024;
49#endif
50
51        while(node != NULL)
52        {
53                if(node->dev == dev)
54                        fbmemcount = fbmemcount + node->varfbsize;
55                node = node->next;
56        }
57       
58        return fix_screeninfo.smem_len - fbmemcount;
59}
60
61struct fb* addfb(char *fbname, int dev, int width, int height, int colbytes, int fd, unsigned char* mmapfb, unsigned long fixfbsize, unsigned long data_phys)
62{
63        struct fb *newnode = NULL, *node = fb;
64        char *name = NULL;
65        long ret = 0;
66
67        name = ostrcat(fbname, NULL, 0, 0);
68        if(name == NULL)
69        {
70                err("no memory");
71                return NULL;
72        }
73
74        newnode = (struct fb*)malloc(sizeof(struct fb));       
75        if(newnode == NULL)
76        {
77                err("no memory");
78                free(name);
79                return NULL;
80        }
81       
82        memset(newnode, 0, sizeof(struct fb));
83        newnode->name = name;
84        newnode->dev = dev;
85        newnode->width = width;
86        newnode->height = height;
87        newnode->colbytes = colbytes;
88        newnode->pitch = newnode->width * newnode->colbytes;
89        newnode->fb = mmapfb;
90        newnode->fblong = (unsigned long*)newnode->fb;
91        newnode->fd = fd;
92        newnode->fixfbsize = fixfbsize;
93        newnode->data_phys = data_phys;
94       
95        if(ostrcmp(name, FB) == 0)
96                setfbvarsize(newnode);
97        else if(ostrcmp(name, FB1) == 0)
98#ifdef MIPSEL
99                newnode->varfbsize = width * height * newnode->colbytes;
100#else           
101                newnode->varfbsize = 720 * 576 * newnode->colbytes;
102#endif
103        else
104                newnode->varfbsize = width * height * newnode->colbytes;
105       
106        if(node != NULL)
107        {
108                while(node->next != NULL)
109                        node = node->next;
110                node->next = newnode;
111        }
112        else
113                fb = newnode;
114               
115        /*eigener Buffer zB fuer LCD*/
116        if(dev == 999)
117                return newnode;
118#ifdef CONFIG_ION
119        if(ostrcmp(name, FB) == 0)
120                ret = getfbsize(dev);
121#else
122        ret = getfbsize(dev);
123#endif
124        if(ret < 0)
125        {
126                err("framebuffermem (%s) to small, needed = %ld", name, ret * -1);
127                free(name);
128                free(newnode);
129                if(newnode == fb) fb = NULL;
130                return NULL;
131        }
132
133        debug(444, "fbname=%s, fbwidth=%d, fbheight=%d, fbcol=%d, fbsize=%ld, phys_addr=%lu", newnode->name, newnode->width, newnode->height, newnode->colbytes, newnode->varfbsize, newnode->data_phys);
134        return newnode;
135}
136
137void fb2png_thread()
138{
139        while (writeFBfile.buf1 != NULL || writeFBfile.buf2 != NULL) {
140                if(writeFBfile.buf1 != NULL) {
141                        writeFBfile.ActBuf = writeFBfile.buf1;
142                        fb2png(writeFBfile.buf1, 320, 240, "/tmp/titanlcd.png");
143                        free(writeFBfile.buf1); writeFBfile.buf1 = NULL;
144                        if(writeFBfile.buf2 != NULL)
145                                usleep(500000);
146                }
147                if(writeFBfile.buf2 != NULL) {
148                        writeFBfile.ActBuf = writeFBfile.buf2;
149                        fb2png(writeFBfile.buf2, 320, 240, "/tmp/titanlcd.png");
150                        free(writeFBfile.buf2); writeFBfile.buf2 = NULL;
151                        if(writeFBfile.buf1 != NULL)
152                                usleep(500000);
153                }
154        }
155        writeFBfile.ActBuf = NULL;
156}
157
158void delfb(char *name)
159{
160        struct fb *node = fb, *prev = fb;
161
162        while(node != NULL)
163        {
164                if(ostrcmp(node->name, name) == 0)
165                {
166                        if(node == fb)
167                                fb = node->next;
168                        else
169                                prev->next = node->next;
170
171                        free(node->name);
172                        node->name = NULL;
173
174                        free(node);
175                        node = NULL;
176                        break;
177                }
178
179                prev = node;
180                node = node->next;
181        }
182}
183
184void freefb()
185{
186        struct fb *node = fb, *prev = fb;
187
188        while(node != NULL)
189        {
190                prev = node;
191                node = node->next;
192                if(prev != NULL)
193                        delfb(prev->name);
194        }
195}
196
197struct fb* openfb(char *fbdev, int devnr)
198{
199        int fd = -1;
200        unsigned char *mmapfb = NULL;
201        struct fb_var_screeninfo var_screeninfo;
202        struct fb_fix_screeninfo fix_screeninfo;
203        struct fb* node = NULL;
204
205        if(fbdev == NULL)
206        {
207                err("failed to find fbdev in config file");
208                return NULL;
209        }
210
211#ifdef CONFIG_ION
212        int ion;
213#endif
214
215#ifndef NOFB
216        fd = open(fbdev, O_RDWR);
217
218// blinking work start
219#ifdef MIPSEL
220        if (fd < 0)
221        {
222                err(fbdev);
223                goto nolfb;
224        }
225#endif
226// blinking work end
227               
228        if(fd == -1)
229        {
230                perr("failed to open %s", fbdev);
231                return NULL;
232        }
233        closeonexec(fd);
234       
235        //workarounnd
236        if(checkchipset("HI3798MV200") == 1)
237        {
238                printf("---> setframebuffer(1280, 720, 1280, 2880, 32)\n");
239                setframebuffer(1280, 720, 1280, 2880, 32);
240        }
241        if(frameb1 == 1)
242        {
243                printf("---> setframebuffer(1920, 1080, 1920, 2160, 32);\n");
244                setframebuffer(1920, 1080, 1920, 2160, 32);
245        }
246       
247       
248        if(ioctl(fd, FBIOGET_VSCREENINFO, &var_screeninfo) == -1)
249        {
250                perr("ioctl FBIOGET_VSCREENINFO failed");
251                close(fd);
252                return NULL;
253        }
254
255        if(ioctl(fd, FBIOGET_FSCREENINFO, &fix_screeninfo) == -1)
256        {
257                perr("ioctl FBIOGET_FSCREENINFO failed");
258                close(fd);
259                return NULL;
260        }
261
262        if(!(mmapfb = (unsigned char*)mmap(0, fix_screeninfo.smem_len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)))
263        {
264                perr("mmap framebuffer");
265                close(fd);
266                return NULL;
267        }
268
269        debug(444, "%dk video mem", fix_screeninfo.smem_len/1024);
270        unsigned long data_phys = 0;   
271#ifdef MIPSEL
272        data_phys = fix_screeninfo.smem_start;
273#ifdef CONFIG_ION
274        /* allocate accel memory here... its independent from the framebuffer */
275        ion = open("/dev/ion", O_RDWR | O_CLOEXEC);
276        if (ion >= 0)
277        {
278                struct ion_allocation_data alloc_data;
279                struct ion_fd_data share_data;
280                struct ion_handle_data free_data;
281                struct ion_phys_data phys_data;
282                int ret;
283               
284                debug(444,"Using ION allocator");
285
286                memset(&alloc_data, 0, sizeof(alloc_data));
287                alloc_data.len = ACCEL_MEM_SIZE;
288                alloc_data.align = 4096; // 4k aligned
289                alloc_data.heap_id_mask = ION_HEAP_ID_MASK;
290                ret = ioctl(ion, ION_IOC_ALLOC, &alloc_data);
291                if (ret < 0)
292                {
293                        err("ION_IOC_ALLOC failed");
294                        err("failed to allocate accel memory!!!");
295                        return NULL;
296                }
297
298                memset(&phys_data, 0, sizeof(phys_data));
299                phys_data.handle = alloc_data.handle;
300                ret = ioctl(ion, ION_IOC_PHYS, &phys_data);
301                if (ret < 0)
302                {
303                        err("ION_IOC_PHYS failed");
304                        goto err_ioc_free;
305                }
306
307                memset(&share_data, 0, sizeof(share_data));
308                share_data.handle = alloc_data.handle;
309                ret = ioctl(ion, ION_IOC_SHARE, &share_data);
310                if (ret < 0)
311                {
312                        err("ION_IOC_SHARE failed");
313                        goto err_ioc_free;
314                }
315
316                memset(&free_data, 0, sizeof(free_data));
317                free_data.handle = alloc_data.handle;
318                if (ioctl(ion, ION_IOC_FREE, &free_data) < 0)
319                        err("ION_IOC_FREE failed");
320
321                m_accel_fd = share_data.fd;
322                lfb=(unsigned char*)mmap(0, ACCEL_MEM_SIZE, PROT_WRITE|PROT_READ, MAP_SHARED, share_data.fd, 0);
323
324                if (lfb)
325                {
326                        debug(444,"%dkB available for acceleration surfaces (via ION).", ACCEL_MEM_SIZE);
327                       
328                        node = addfb(FB, devnr, var_screeninfo.xres, var_screeninfo.yres, var_screeninfo.bits_per_pixel / 8, fd, mmapfb, fix_screeninfo.smem_len, data_phys);
329                        skinfb = addfb(SKINFB, 0, getconfigint("skinfbwidth", NULL), getconfigint("skinfbheight", NULL), 4, share_data.fd, lfb, ACCEL_MEM_SIZE, phys_data.addr);
330                        accelfb = addfb(ACCELFB, 0, (ACCEL_MEM_SIZE-(skinfb->width*skinfb->height*4)) / 4, 1, 4, share_data.fd, skinfb->fb + skinfb->varfbsize, ACCEL_MEM_SIZE, skinfb->data_phys + skinfb->varfbsize);
331                }
332                else
333                {
334                        close(m_accel_fd);
335                        err("mmap lfb failed");
336err_ioc_free:
337                        err("failed to allocate accel memory via ION!!!");
338                        m_accel_fd = -1;
339                        memset(&free_data, 0, sizeof(free_data));
340                        free_data.handle = alloc_data.handle;
341                        if (ioctl(ion, ION_IOC_FREE, &free_data) < 0)
342                                err("ION_IOC_FREE");
343                }
344                close(ion);
345        }
346        else
347        {
348                err("failed to open ION device node! no allocate accel memory available !!");
349                m_accel_fd = -1;
350        }
351        if (!lfb)
352        {
353                err("mmap");
354                goto nolfb;
355        }
356#else
357        lfb = (unsigned char*)mmap(0, fix_screeninfo.smem_len, PROT_WRITE|PROT_READ, MAP_SHARED, fd, 0);
358        if (!lfb)
359        {
360                err("mmap");
361                goto nolfb;
362        }
363
364        if (var_screeninfo.bits_per_pixel != 32)
365        {
366                debug(444, "Only 32 bit per pixel supported. Framebuffer currently use %d", var_screeninfo.bits_per_pixel);
367                closefb();
368                return 0;
369        }
370#endif 
371#endif
372#ifndef CONFIG_ION
373        if(devnr == 0)
374                node = addfb(FB, devnr, var_screeninfo.xres, var_screeninfo.yres, var_screeninfo.bits_per_pixel / 8, fd, mmapfb, fix_screeninfo.smem_len, data_phys);
375        if(devnr == 1)
376                node = addfb(FB1, devnr, var_screeninfo.xres, var_screeninfo.yres, var_screeninfo.bits_per_pixel / 8, fd, mmapfb, fix_screeninfo.smem_len, data_phys);
377
378#endif         
379
380#else
381        mmapfb = malloc(16 * 1024 * 1024);
382        if(devnr == 0)
383                node = addfb(FB, devnr, getconfigint("skinfbwidth", NULL), getconfigint("skinfbheight", NULL), 4, -1, mmapfb, 16*1024*1024, 0);
384        if(devnr == 1)
385                node = addfb(FB1, devnr, getconfigint("skinfbwidth", NULL), getconfigint("skinfbheight", NULL), 4, -1, mmapfb, 16*1024*1024, 0);
386
387#endif
388
389        return node;
390
391#ifdef MIPSEL
392nolfb:
393        if (fd >= 0)
394        {
395                close(fd);
396                fd = -1;
397        }
398
399        debug(444, "framebuffer not available.");
400#endif
401        return 0;
402// blinking work end
403}
404
405void closefb()
406{
407
408#ifdef MIPSEL
409        if(lfb)
410        {
411                debug(444, "ms_sync");
412                msync(lfb, fix_screeninfo.smem_len, MS_SYNC);
413                munmap(lfb, fix_screeninfo.smem_len);
414        }
415        if(fb->fd >= 0)
416        {
417                debug(444, "close");
418                disablemanualblit();
419                close(fb->fd);
420                fb->fd = -1;
421        }
422#endif
423
424        if(fb != NULL)
425        {
426                if(fb->fb != NULL)
427                        munmap(fb->fb, fb->fixfbsize);
428                if(fb->fd != -1)
429                        close(fb->fd);
430#ifdef NOFB
431                free(fb->fb);
432#endif
433        }
434}
435
436void clearfball()
437{
438        if(fb != NULL && fb->fb != NULL)
439                memset(fb->fb, 0, fb->fixfbsize);
440}
441
442void clearfb(struct fb *node)
443{
444        if(node != NULL)
445                memset(node->fb, 0, node->varfbsize);
446}
447
448void blitfb(int flag)
449{
450        blitfb2(skinfb, flag);
451}
452
453void blitfb1()
454{
455        blitfb2(skinfb, 0);
456}
457
458//flag 0: del skinfb
459//flag 1: don't del skinfb
460void changefbresolution(char *value, int flag)
461{
462        debug(444, "fb->colbytes: %d", fb->colbytes);
463#ifdef MIPSEL
464        return;
465#endif
466
467        if(ostrcmp("pal", value) == 0)
468        {
469                fb->width = 720;
470                fb->height = 576;
471                fb->pitch = fb->width * fb->colbytes;
472        }
473        else if(ostrncmp("576", value, 3) == 0)
474        {
475                fb->width = 720;
476                fb->height = 576;
477                fb->pitch = fb->width * fb->colbytes;
478        }
479        else if(ostrncmp("720", value, 3) == 0)
480        {
481                fb->width = 1280;
482                fb->height = 720;
483                fb->pitch = fb->width * fb->colbytes;
484        }
485        else if(ostrncmp("1080", value, 4) == 0)
486        {
487                fb->width = 1920;
488                fb->height = 1080;
489                fb->pitch = fb->width * fb->colbytes;
490        }
491        if(skinfb == fb)
492        {
493                skin->width = skinfb->width;
494                skin->height = skinfb->height;
495                skin->iwidth = skinfb->width;
496                skin->iheight = skinfb->height;
497                skin->rwidth = skinfb->width;
498                skin->rheight = skinfb->height;
499        }
500        clearfb(fb);
501        if(flag == 0) clearfb(skinfb);
502}
503
504static void write_PNG(unsigned char *outbuffer, char *filename,
505                                int width, int height, int interlace)
506{
507        int i;
508        int bit_depth=0, color_type;
509        png_bytep row_pointers[height];
510        png_structp png_ptr;
511        png_infop info_ptr;
512        FILE *outfile = fopen(filename, "wb");
513
514        for (i=0; i<height; i++)
515                row_pointers[i] = outbuffer + i * 4 * width;
516               
517        if (!outfile)
518        {
519                fprintf (stderr, "Error: Couldn't fopen %s.\n", filename);
520                exit(EXIT_FAILURE);
521        }
522   
523        png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
524        (png_voidp) NULL, (png_error_ptr) NULL, (png_error_ptr) NULL);
525   
526        if (!png_ptr)
527                err("Error: Couldn't create PNG write struct.");
528   
529        info_ptr = png_create_info_struct(png_ptr);
530        if (!info_ptr)
531        {
532                png_destroy_write_struct(&png_ptr, (png_infopp) NULL);
533                err("Error: Couldn't create PNG info struct.");
534        }
535   
536        png_init_io(png_ptr, outfile);
537   
538        png_set_compression_level(png_ptr, Z_BEST_COMPRESSION);
539   
540        bit_depth = 8;
541        color_type = PNG_COLOR_TYPE_RGB_ALPHA;
542        //color_type = PNG_COLOR_TYPE_RGB;
543        png_set_invert_alpha(png_ptr);
544        png_set_bgr(png_ptr);
545
546        png_set_IHDR(png_ptr, info_ptr, width, height,
547        bit_depth, color_type, interlace,
548        PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
549   
550        png_write_info(png_ptr, info_ptr);
551   
552        printf ("Now writing PNG file\n");
553   
554        png_write_image(png_ptr, row_pointers);
555   
556        png_write_end(png_ptr, info_ptr);
557        /* puh, done, now freeing memory... */
558        png_destroy_write_struct(&png_ptr, &info_ptr);
559   
560        if (outfile != NULL)
561                (void) fclose(outfile);
562}
563
564static void convert_and_write(unsigned char *inbuffer, char *filename,
565                                int width, int height, int bits, int interlace)
566{
567        size_t bufsize = (size_t) width * height * 4;
568
569        unsigned char *outbuffer = malloc(bufsize);
570
571        if (outbuffer == NULL)
572                err("Not enough memory");
573       
574        memset(outbuffer, 0, bufsize);
575        write_PNG(inbuffer, filename, width, height, interlace);
576        (void) free(outbuffer);
577}
578
579int fb2png(unsigned char *buf_p, int width, int height, char *outfile)
580{
581        int interlace = PNG_INTERLACE_ADAM7;
582        int bitdepth = 32;
583               
584        size_t help = 0;
585        while(help <= (width * height * 4))
586        {
587                buf_p[help+3] = 0x00;
588                help = help + 4;
589        }
590               
591        convert_and_write(buf_p, outfile, width, height, bitdepth, interlace);
592
593        return 0;
594}
595
596void pngforlcd(unsigned char *fbuffer, int width, int height)
597{
598        fb2png(fbuffer, width, height, "/tmp/titanlcd.png");
599}
600
601void write_FB_to_JPEG_file(unsigned char *inbuffer, int image_width, int image_height, char * filename, int quality)
602{               
603        size_t helpb = 0;
604        size_t help = 0;
605        unsigned char *helpbuffer = malloc(image_width*image_height*3);
606       
607        //delete alpha byte
608        while(help <= (image_width*image_height*4))
609        {
610                helpbuffer[helpb+0] = inbuffer[help+2];
611                helpbuffer[helpb+1] = inbuffer[help+1];
612                helpbuffer[helpb+2] = inbuffer[help+0];
613                help = help + 4;
614                helpb = helpb + 3;
615        }
616       
617        JSAMPLE *image_buffer = helpbuffer;
618        struct jpeg_compress_struct cinfo;
619        struct jpeg_error_mgr jerr;
620        FILE * outfile;
621       
622        JSAMPROW row_pointer[1];
623        int row_stride;
624       
625        cinfo.err = jpeg_std_error(&jerr);
626        jpeg_create_compress(&cinfo);
627        if ((outfile = fopen(filename, "wb")) == NULL) {
628                fprintf(stderr, "can't open %s\n", filename);
629                exit(1);
630        }
631        jpeg_stdio_dest(&cinfo, outfile);
632        cinfo.image_width = image_width;        /* image width and height, in pixels */
633        cinfo.image_height = image_height;
634        cinfo.input_components = 3;             /* # of color components per pixel */
635        cinfo.in_color_space = JCS_RGB;
636
637        jpeg_set_defaults(&cinfo);
638        jpeg_set_quality(&cinfo, quality, TRUE);
639
640        jpeg_start_compress(&cinfo, TRUE);
641        row_stride = image_width * 3;
642
643        while (cinfo.next_scanline < cinfo.image_height) {
644                row_pointer[0] = & image_buffer[cinfo.next_scanline * row_stride];
645                (void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
646        }
647
648        jpeg_finish_compress(&cinfo);
649        fclose(outfile);
650        jpeg_destroy_compress(&cinfo);
651   
652        free(helpbuffer);
653}
654
655int setframebuffer(int width, int height, int vwidth, int vheight, int bits)
656{
657        struct fb_var_screeninfo var_screeninfo;
658        int fd = -1;
659        char *fbdev = getconfig("fbdev", NULL);
660       
661        if(fbdev == NULL)
662        {
663                err("failed to find fbdev in config file");
664                return -1;
665        }
666
667        fd = open(fbdev, O_RDWR);
668        if(fd == -1)
669        {
670                perr("failed to open %s", fbdev);
671                return -1;
672        }
673       
674        if(ioctl(fd, FBIOGET_VSCREENINFO, &var_screeninfo) < 0)
675        {
676                err("failed to read VSCREENINFO");
677                close(fd);
678                return -1;
679        }
680
681        var_screeninfo.xres = width;
682        var_screeninfo.yres = height;
683        var_screeninfo.xres_virtual = vwidth;
684        var_screeninfo.yres_virtual = vheight;
685        var_screeninfo.bits_per_pixel  = bits;
686
687        if(ioctl(fd, FBIOPUT_VSCREENINFO, &var_screeninfo) < 0)
688        {
689                err("failed to put VSCREENINFO");
690                close(fd);
691                return -1;
692        }
693       
694        printf("---> FBIOPUT_VSCREENINFO endet\n");
695        system("fbset");
696               
697        close(fd);
698        return 0;       
699}
700
701#ifdef OEBUILD
702int saveframebuffer()
703{
704        int fd = -1;
705        char *fbdev = getconfig("fbdev", NULL);
706       
707        if(fbdev == NULL)
708        {
709                err("failed to find fbdev in config file");
710                return -1;
711        }
712
713        fd = open(fbdev, O_RDWR);
714        if(fd == -1)
715        {
716                perr("failed to open %s", fbdev);
717                return -1;
718        }
719        //workaround
720        if(checkchipset("HI3798MV200") == 1)
721        {
722                printf("---> setframebuffer(1280, 720, 1280, 2880, 32)\n");
723                setframebuffer(1280, 720, 1280, 2880, 32);
724        }
725        if(frameb1 == 1)
726        {
727                printf("---> setframebuffer(1920, 1080, 1920, 2160, 32)\n");
728                setframebuffer(1920, 1080, 1920, 2160, 32);
729        }
730       
731        if(ioctl(fd, FBIOGET_VSCREENINFO, &save_var_screeninfo) < 0)
732        {
733                err("failed to read VSCREENINFO");
734                close(fd);
735                return -1;
736        }
737
738        close(fd);
739        return 0;       
740}
741
742int restoreframebuffer()
743{
744        int fd = -1;
745        char *fbdev = getconfig("fbdev", NULL);
746       
747        if(fbdev == NULL)
748        {
749                err("failed to find fbdev in config file");
750                return -1;
751        }
752
753        fd = open(fbdev, O_RDWR);
754        if(fd == -1)
755        {
756                perr("failed to open %s", fbdev);
757                return -1;
758        }
759       
760        if(ioctl(fd, FBIOPUT_VSCREENINFO, &save_var_screeninfo) < 0)
761        {
762                err("failed to write VSCREENINFO");
763                close(fd);
764                return -1;
765        }
766
767        close(fd);
768        return 0;       
769}
770#endif
771
772
773#endif
Note: See TracBrowser for help on using the repository browser.