00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086 #define FULL_WIDTH ( get_imageParamsThis(P_ACTUAL_WIDTH)+4 )
00087 #define FULL_HEIGHT ( get_imageParamsThis(P_ACTUAL_HEIGHT)+4 )
00088
00089 #include <linux/module.h>
00090 #include <linux/sched.h>
00091 #include <linux/slab.h>
00092 #include <linux/errno.h>
00093 #include <linux/kernel.h>
00094 #include <linux/fs.h>
00095 #include <linux/string.h>
00096 #include <linux/init.h>
00097 #include <linux/autoconf.h>
00098
00099 #include <asm/system.h>
00100
00101 #include <asm/io.h>
00102
00103 #include <asm/irq.h>
00104
00105 #include <asm/delay.h>
00106 #include <asm/uaccess.h>
00107 #include <asm/elphel/driver_numbers.h>
00108 #include <asm/elphel/c313a.h>
00109
00110 #include "fpgactrl.h"
00111 #include "framepars.h"
00112
00113 #include "x3x3.h"
00114
00115 #include "cxsdram.h"
00116
00117 #define D(x)
00118 #if ELPHEL_DEBUG
00119 #define MDF(x) {printk("%s:%d:%s ",__FILE__,__LINE__,__FUNCTION__);x ;}
00120 #else
00121 #define MDF(x)
00122 #endif
00123
00124
00125
00126
00127 #define IMAGERAW_MODULE_DESCRIPTION "Raw image access driver for Elphel 353 camera"
00128 #define IMAGERAW_DRIVER_NAME "Raw image access driver"
00129 static const char x353raw_name[] = "elphel_raw353";
00130
00131
00132 static int linebuf_fpn[4096];
00133 static int lineinbuf_fpn;
00134 static int linebufdirty_fpn = 0;
00135 static int linebuf_img[4096];
00136 static int lineinbuf_img;
00137 static int linebufdirty_img = 0;
00138
00139 static int minor_lock=0;
00140
00141
00142 int * x353raw_fpn_readline(int line, int ignore);
00143 int x353raw_fpn_writeline(void);
00144 ssize_t x353raw_fpn_read(struct file * file, char * buf, size_t count, loff_t *off);
00145 ssize_t x353raw_fpn_write(struct file * file, const char * buf, size_t count, loff_t *off);
00146 int * x353raw_frame_readline(int line, int ignore);
00147 int x353raw_frame_writeline(void);
00148 ssize_t x353raw_frame_read(struct file * file, char * buf, size_t count, loff_t *off);
00149 ssize_t x353raw_frame_write(struct file * file, const char * buf, size_t count, loff_t *off);
00150 loff_t x353raw_frame_lseek(struct file * file, loff_t offset, int orig);
00151 void x353raw_frame_release(void);
00152 int x353raw_frame_open(struct inode *inode, struct file *filp);
00153 int x353raw_fpn_open(struct inode *inode, struct file *filp);
00154 loff_t x353raw_fpn_lseek(struct file * file, loff_t offset, int orig);
00155 void x353raw_fpn_release(void);
00156 void x353raw_f_invalidate (void);
00157
00158 int x353raw_open(struct inode *inode, struct file *filp);
00159 int x353raw_release(struct inode *inode, struct file *filp);
00160 loff_t x353raw_lseek (struct file * file, loff_t offset, int orig);
00161 ssize_t x353raw_write(struct file * file, const char * buf, size_t count, loff_t *off);
00162 ssize_t x353raw_read(struct file * file, char * buf, size_t count, loff_t *off);
00163
00164
00165
00166
00167
00168 int *x353raw_fpn_readline(int line, int ignore) {
00169 int ntilex, padlen, sa, nw, n, i, li;
00170
00171 if(line == lineinbuf_fpn)
00172 return linebuf_fpn;
00173 if((port_csp0_addr[X313_WA_SD_MODE] & 3) != 3)
00174 return NULL;
00175 if(linebufdirty_fpn) {
00176 if (x353raw_fpn_writeline() < 0)
00177 return NULL;
00178 }
00179 lineinbuf_fpn = line;
00180 if(ignore) return linebuf_fpn;
00181 nw = ((FULL_WIDTH + 1) >> 1);
00182 ntilex = ((nw + 3) >> 2);
00183 padlen = ((ntilex + 31) >> 5);
00184 sa = X313_MAP_FPN + ((padlen * line) << 8);
00185 X313_INIT_SDCHAN(3, 0, 0, 0, sa, 0x3ff, 0xfff);
00186
00187 X313_CHN_EN(3);
00188 li = 0;
00189 while (nw > 0) {
00190 i = 1000;
00191 D(printk("wait "));
00192 while (((i--) > 0) && !X313_SR(PIORDY)) udelay(1);
00193 D(printk("ready, i=%d\n", (int) i));
00194 if (i == 0)
00195 return NULL;
00196 n = nw;
00197 if (n > 128)
00198 n = 128;
00199 i = RD_SD_PIOWIN;
00200 for (i = 0; i < n; i++)
00201 linebuf_fpn[li++] = RD_SD_PIOWIN;
00202 nw -= n;
00203 if (nw > 0)
00204 port_csp0_addr[X313_WA_SDPIO_NEXT] = 0;
00205 }
00206 return linebuf_fpn;
00207 }
00208
00209 int x353raw_fpn_writeline(void) {
00210 int ntilex, padlen, sa, nw, n, i, li;
00211
00212 if(linebufdirty_fpn == 0)
00213 return 0;
00214 if(lineinbuf_fpn >= 0) {
00215 if((port_csp0_addr[X313_WA_SD_MODE] & 3) != 3) return -1;
00216 nw = ((FULL_WIDTH + 1) >> 1);
00217 ntilex = ((nw + 3) >> 2);
00218 padlen = ((ntilex + 31) >> 5);
00219 sa = X313_MAP_FPN + ((padlen * lineinbuf_fpn) << 8);
00220 X313_INIT_SDCHAN(3, 0, 1, 0, sa, 0x3ff, 0xfff);
00221
00222 X313_CHN_EN(3);
00223
00224 li = 0;
00225 while (nw > 0) {
00226 i = 1000;
00227 D(printk("wait "));
00228 while (((i--) > 0) && !X313_SR(PIORDY)) udelay(1);
00229 D(printk("ready, i=%d\n", (int) i));
00230 if (i == 0) return -1;
00231 n = nw;
00232 if (n > 128)
00233 n = 128;
00234 for (i = 0; i < n; i++)
00235 port_csp0_addr[X313_WA_SD_PIOWIN] = linebuf_fpn[li++];
00236 nw -= n;
00237 port_csp0_addr[X313_WA_SDPIO_NEXT] = 0;
00238 }
00239
00240
00241
00242
00243
00245 i = 1000;
00246 while (((i--) > 0) && !X313_SR(PIOWEMPTY)) udelay(1);
00247 if (i == 0)
00248 return -EFAULT;
00249 }
00250 linebufdirty_fpn = 0;
00251 return 0;
00252 }
00253
00254
00255 ssize_t x353raw_fpn_read(struct file * file, char *buf, size_t count, loff_t * off) {
00256 unsigned long p, fsz, y, xb, xbl, left;
00257 char *bp = buf;
00258 char *mp;
00259
00260 MDF(printk("count=%x, off=%x\n", (int) count, (int) off));
00262 p = *off;
00263
00264 fsz = (FULL_WIDTH * FULL_HEIGHT) << 1;
00265
00266 if((p + count) > fsz) {
00267 count = fsz - p;
00268 }
00269 left = count;
00270 while(left > 0) {
00271
00272
00273 y = (p / FULL_WIDTH) >> 1;
00274
00275 xb = p - y * (FULL_WIDTH << 1);
00276 xbl = (FULL_WIDTH << 1) - xb;
00277 if(xbl > left)
00278 xbl = left;
00279 if(!(mp = (char *)x353raw_fpn_readline(y, 0)))
00280 return -EFAULT;
00281
00282 mp += xb;
00283
00284 if(copy_to_user(bp, mp, xbl))
00285 return -EFAULT;
00286 left -= xbl;
00287 p += xbl;
00288 bp += xbl;
00289 }
00290
00291 *off+=count;
00292 return count;
00293 }
00294
00295 ssize_t x353raw_fpn_write(struct file * file, const char *buf, size_t count, loff_t * off) {
00296 unsigned long p, fsz, y, xb, xbl, left;
00297 const char *bp = buf;
00298 char *mp;
00299
00300
00302 p=*off;
00303 fsz = (FULL_WIDTH * FULL_HEIGHT) << 1;
00304 if (p >= fsz)
00305 return -EINVAL;
00306 if ((p + count) > fsz) {
00307 count = fsz - p;
00308 }
00309 left = count;
00310 while (left > 0) {
00311
00312 y = (p / FULL_WIDTH) >> 1;
00313 xb = p - y * (FULL_WIDTH << 1);
00314 xbl = (FULL_WIDTH << 1) - xb;
00315 if (xbl > left)
00316 xbl = left;
00317
00318 if (!(mp = (char *) x353raw_fpn_readline(y, ((xb == 0) && (xbl == (FULL_WIDTH << 1))))))
00319 return -EFAULT;
00320
00321 mp += xb;
00322 if (copy_from_user(mp, bp, xbl))
00323 return -EFAULT;
00324 left -= xbl;
00325 p += xbl;
00326 bp += xbl;
00327 linebufdirty_fpn = 1;
00328 }
00329
00330 *off+=count;
00331 return count;
00332 }
00333
00334
00335 loff_t x353raw_fpn_lseek(struct file * file, loff_t offset, int orig) {
00336
00337
00338
00339
00340
00341
00342 unsigned long fsz;
00343
00344 fsz = (FULL_WIDTH * FULL_HEIGHT) << 1;
00345
00346 MDF(printk("orig= %x, offset=k %x\n",(int) orig, (int) offset));
00347 switch (orig) {
00348 case 0:
00349 file->f_pos = offset;
00350 break;
00351 case 1:
00352 file->f_pos += offset;
00353 break;
00354 case 2:
00355 file->f_pos = fsz + offset;
00356 break;
00357 default:
00358 return -EINVAL;
00359 }
00360
00361
00362 if (file->f_pos < 0) {
00363 file->f_pos = 0;
00364 return (-EOVERFLOW);
00365 }
00366
00367 if (file->f_pos > fsz) {
00368 file->f_pos = fsz;
00369 return (-EOVERFLOW);
00370 }
00371 return (file->f_pos);
00372 }
00373
00374
00375
00376 int *x353raw_frame_readline(int line, int ignore) {
00377 int ntilex, padlen, sa, nw, n, i, li;
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388 if(line == lineinbuf_img)
00389 return linebuf_img;
00390 if((port_csp0_addr[X313_WA_SD_MODE] & 3) != 3)
00391 return NULL;
00392 if(linebufdirty_img) {
00393 if (x353raw_frame_writeline() < 0)
00394 return NULL;
00395 }
00396 lineinbuf_img = line;
00397 if(ignore) return linebuf_img;
00398 if((get_imageParamsThis(P_BITS) == 8) && !get_imageParamsThis(P_BGFRAME))
00399 nw = ((FULL_WIDTH + 3) >> 2);
00400 else
00401 nw = ((FULL_WIDTH + 1) >> 1);
00402 ntilex = ((nw + 3) >> 2);
00403 padlen = ((ntilex + 31) >> 5);
00404
00405
00406
00407
00408
00409 sa = X313_MAP_FRAME + ((padlen * line) << 8);
00410
00411
00412 X313_INIT_SDCHAN(3, 0, 0, 0, sa, 0x3ff, 0xfff);
00413
00414
00415
00416
00417 X313_CHN_EN(3);
00418
00419 li = 0;
00420 while(nw > 0) {
00421 i = 1000;
00422 D(printk("wait "));
00423 while(((i--) > 0) && !X313_SR(PIORDY)) udelay(1);
00424 D(printk("ready, i = %d\n", (int) i));
00425 if(i == 0)
00426 return NULL;
00427 n = nw;
00429 if(n > 128) n = 128;
00431 i = RD_SD_PIOWIN;
00432 for(i = 0; i < n; i++)
00433
00434 linebuf_img[li++] = RD_SD_PIOWIN;
00435 nw -= n;
00436 if(nw > 0)
00437 port_csp0_addr[X313_WA_SDPIO_NEXT] = 0;
00438 }
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495 return linebuf_img;
00496 }
00497
00498 int x353raw_frame_writeline(void) {
00499 int ntilex, padlen, sa, nw, n, i, li;
00500 if(linebufdirty_img == 0) {
00501 MDF(printk("lineinbuf_img=0x%x, linebufdirty_img=0x%x\n", lineinbuf_img, linebufdirty_img));
00502 return 0;
00503 }
00504 if(lineinbuf_img >= 0) {
00505 if((port_csp0_addr[X313_WA_SD_MODE] & 3) != 3) return -1;
00506 if((get_imageParamsThis(P_BITS) == 8) && !get_imageParamsThis(P_BGFRAME))
00507 nw = ((FULL_WIDTH + 3) >> 2);
00508 else
00509 nw = ((FULL_WIDTH + 1) >> 1);
00510 ntilex = ((nw + 3) >> 2);
00511 padlen = ((ntilex + 31) >> 5);
00512 sa = X313_MAP_FRAME + ((padlen * lineinbuf_img) << 8);
00513
00514 i=1000;
00515 while (((i--)>0) && !X313_SR(PIOWEMPTY)) udelay(1);
00516 if (i==0) return -EFAULT;
00517
00518 X313_INIT_SDCHAN(3, 0, 1, 0, sa, 0x3ff, 0xfff);
00519 MDF(printk("lineinbuf_img=0x%x, sa=0x%x, nw=0x%x\n", lineinbuf_img, sa, nw));
00520 X313_CHN_EN(3);
00521
00522 li = 0;
00523 while (nw > 0) {
00524 i = 1000;
00525 MDF(printk("wait, nw=0x%x : ", nw));
00526 while (((i--) > 0) && !X313_SR(PIORDY)) udelay(1);
00527 MDF(printk("ready, i=%d\n", (int) i));
00528 if (i == 0) return -EFAULT;
00529 n = nw;
00531 if (n > 128) n = 128;
00532 for (i = 0; i < n; i++) port_csp0_addr[X313_WA_SD_PIOWIN] = linebuf_img[li++];
00533 nw -= n;
00534 port_csp0_addr[X313_WA_SDPIO_NEXT] = 0;
00535 }
00538 i = 1000;
00539 while (((i--) > 0) && !X313_SR(PIOWEMPTY)) udelay(1);
00540 if (i == 0)
00541 return -EFAULT;
00542 }
00543 linebufdirty_img = 0;
00544 return 0;
00545 }
00546
00547
00548 ssize_t x353raw_frame_read(struct file * file, char *buf, size_t count, loff_t * off) {
00549 unsigned long p, fsz, y, xb, xbl, left;
00550 char *bp = buf;
00551 char *mp;
00552 p=*off;
00553 MDF(printk("count = %x, off = %x, f_pos = %d\r\n", (int)count, (int)off, (int) p));
00554 fsz = (FULL_WIDTH * FULL_HEIGHT) << (((get_imageParamsThis(P_BITS) == 8) && !get_imageParamsThis(P_BGFRAME)) ? 0 : 1);
00555 MDF(printk("FULL_WIDTH = 0x%x, FULL_HEIGHT = 0x%x, fsz = 0x%x\r\n", (int) FULL_WIDTH, (int)FULL_HEIGHT, (int) fsz));
00556 if((p + count) > fsz) {
00557 count = fsz - p;
00558 }
00559 left = count;
00560 while(left > 0) {
00561
00562 if((get_imageParamsThis(P_BITS) == 8) && !get_imageParamsThis(P_BGFRAME)) {
00563 y = p / FULL_WIDTH;
00564 xb = p - y * FULL_WIDTH;
00565 xbl = FULL_WIDTH - xb;
00566 } else {
00567 y = (p / FULL_WIDTH) >> 1;
00568 xb = p - y * (FULL_WIDTH << 1);
00569 xbl = (FULL_WIDTH << 1) - xb;
00570 }
00571 if(xbl > left)
00572 xbl = left;
00573 if(!(mp = (char *)x353raw_frame_readline(y + FULL_HEIGHT * get_imageParamsThis(P_PAGE_READ), 0))) {
00574 printk("read SDRAM error!\r\n");
00575 return -EFAULT;
00576 }
00577
00578 mp += xb;
00579
00580 if(copy_to_user(bp, mp, xbl)) {
00581 printk("copy_to_user error!\r\n");
00582 return -EFAULT;
00583 }
00584 left -= xbl;
00585 p += xbl;
00586 bp += xbl;
00587 }
00588
00589 *off+=count;
00590
00591 return count;
00592 }
00593
00594 ssize_t x353raw_frame_write(struct file * file, const char * buf, size_t count, loff_t *off) {
00595 unsigned long p, fsz, y, xb, xbl, left, bytes_in_line;
00596 const char *bp = buf;
00597 char *mp;
00598 p=*off;
00599
00600 fsz = (FULL_WIDTH * FULL_HEIGHT) << (((get_imageParamsThis(P_BITS) == 8) && !get_imageParamsThis(P_BGFRAME)) ? 0 : 1);
00601
00602 if (p >= fsz) return -EINVAL;
00603 if ((p + count) > fsz) {
00604 count = fsz - p;
00605 }
00606 left = count;
00607 MDF(printk("count == %x, off == %x, f_pos == %d\r\n", (int)count, (int)off, (int) p));
00608 while (left > 0) {
00610 if((get_imageParamsThis(P_BITS) == 8) && !get_imageParamsThis(P_BGFRAME)) {
00611 y = p / FULL_WIDTH;
00612 xb = p - y * FULL_WIDTH;
00613 bytes_in_line = FULL_WIDTH;
00614 xbl = bytes_in_line - xb;
00615 } else {
00616 y = (p / FULL_WIDTH) >> 1;
00617 xb = p - y * (FULL_WIDTH << 1);
00618 bytes_in_line = (FULL_WIDTH <<1);
00619 xbl = bytes_in_line - xb;
00620 }
00621 if (xbl > left) xbl = left;
00622
00624 if (!(mp = (char *) x353raw_frame_readline(y, ((xb == 0) && (xbl == bytes_in_line))))) return -EFAULT;
00625
00626 mp += xb;
00627 if (copy_from_user(mp, bp, xbl)) return -EFAULT;
00628 left -= xbl;
00629 p += xbl;
00630 bp += xbl;
00631 linebufdirty_img = 1;
00632 }
00633 *off+=count;
00634 return count;
00635 }
00636
00637
00638
00639
00640 loff_t x353raw_frame_lseek(struct file * file, loff_t offset, int orig) {
00641
00642
00643
00644
00645
00646
00647 unsigned long fsz;
00648 fsz = (FULL_WIDTH * FULL_HEIGHT) << (((get_imageParamsThis(P_BITS) == 8) && !get_imageParamsThis(P_BGFRAME)) ? 0 : 1);
00649
00650
00651
00652 switch (orig) {
00653 case 0:
00654 file->f_pos = offset;
00655 break;
00656 case 1:
00657 file->f_pos += offset;
00658 break;
00659 case 2:
00660 file->f_pos = fsz + offset;
00661 break;
00662 default:
00663 return -EINVAL;
00664 }
00665
00666
00667 if (file->f_pos < 0) {
00668 file->f_pos = 0;
00669 return (-EOVERFLOW);
00670 }
00671
00672 if (file->f_pos > fsz) {
00673 file->f_pos = fsz;
00674 return (-EOVERFLOW);
00675 }
00676 return (file->f_pos);
00677 }
00678
00679 int x353raw_frame_open(struct inode *inode, struct file *filp) {
00680 inode->i_size = (FULL_WIDTH * FULL_HEIGHT) << (((get_imageParamsThis(P_BITS) == 8) && !get_imageParamsThis(P_BGFRAME)) ? 0 : 1);
00681 linebufdirty_fpn = 0;
00682 lineinbuf_img = -1;
00683
00684
00685 return 0;
00686 }
00687
00688 void x353raw_frame_release(void) {
00689 if(linebufdirty_img) x353raw_frame_writeline();
00690 MDF(printk("\n"));
00691
00692 }
00693
00694 int x353raw_fpn_open(struct inode *inode, struct file *filp) {
00695 inode->i_size = (FULL_WIDTH * FULL_HEIGHT) << 1;
00696 linebufdirty_fpn = 0;
00697 lineinbuf_fpn = -1;
00698 MDF(printk("size = %x\n", (int) inode->i_size));
00699 return 0;
00700 }
00701
00702 void x353raw_fpn_release(void) {
00703 if(linebufdirty_fpn)
00704 x353raw_fpn_writeline();
00705 MDF(printk("\n"));
00706
00707 }
00708
00709 void x353raw_f_invalidate(void) {
00710 linebufdirty_fpn = 0;
00711 linebufdirty_img = 0;
00712 lineinbuf_fpn = -1;
00713 lineinbuf_img = -1;
00714 }
00715
00717
00718
00719 static struct file_operations x353raw_fops = {
00720 owner: THIS_MODULE,
00721 llseek: x353raw_lseek,
00722 read: x353raw_read,
00723 write: x353raw_write,
00724 open: x353raw_open,
00725 release: x353raw_release
00726 };
00727
00728 static int __init x353raw_init(void) {
00729 int res;
00730 res = register_chrdev(IMAGERAW_MAJOR, x353raw_name, &x353raw_fops);
00731 if(res < 0) {
00732 printk(KERN_ERR "x353raw_init: couldn't get a major number %d.\n",IMAGERAW_MAJOR);
00733 return res;
00734 }
00735 printk(IMAGERAW_DRIVER_NAME"- %d\n", IMAGERAW_MAJOR);
00736 return 0;
00737 }
00738
00739
00740
00741
00742
00743
00744 int x353raw_open(struct inode *inode, struct file *filp) {
00745 int res=0;
00746 int p = MINOR(inode->i_rdev);
00747 switch (p) {
00748 case IMAGERAW_MINOR_UNLOCK:
00749 minor_lock=0;
00750 return 0;
00751 case IMAGERAW_MINOR_FRAME:
00752 if (minor_lock) return -EACCES;
00753 res=x353raw_frame_open(inode, filp);
00754 break;
00755 case IMAGERAW_MINOR_FPN:
00756 if (minor_lock) return -EACCES;
00757 res=x353raw_fpn_open(inode, filp);
00758 break;
00759 default: return -EINVAL;
00760 }
00761 minor_lock=p;
00762 return 0;
00763 }
00764
00765 int x353raw_release(struct inode *inode, struct file *filp) {
00766 int p = MINOR(inode->i_rdev);
00767 switch (p) {
00768 case IMAGERAW_MINOR_UNLOCK:
00769 break;
00770 case IMAGERAW_MINOR_FRAME:
00771 x353raw_frame_release();
00772 break;
00773 case IMAGERAW_MINOR_FPN:
00774 x353raw_fpn_release();
00775 break;
00776 default: return -EINVAL;
00777 }
00778 minor_lock=0;
00779 return 0;
00780 }
00781
00782 loff_t x353raw_lseek (struct file * file, loff_t offset, int orig) {
00783 switch (minor_lock) {
00784 case IMAGERAW_MINOR_FRAME: return x353raw_frame_lseek(file, offset, orig);
00785 case IMAGERAW_MINOR_FPN: return x353raw_fpn_lseek (file, offset, orig);
00786 default: return -EINVAL;
00787 }
00788 }
00789
00790 ssize_t x353raw_write(struct file * file, const char * buf, size_t count, loff_t *off) {
00791 switch (minor_lock) {
00792 case IMAGERAW_MINOR_FRAME: return x353raw_frame_write(file, buf, count, off);
00793 case IMAGERAW_MINOR_FPN: return x353raw_fpn_write (file, buf, count, off);
00794 default: return -EINVAL;
00795 }
00796 }
00797
00798 ssize_t x353raw_read(struct file * file, char * buf, size_t count, loff_t *off) {
00799 switch (minor_lock) {
00800 case IMAGERAW_MINOR_FRAME: return x353raw_frame_read(file, buf, count, off);
00801 case IMAGERAW_MINOR_FPN: return x353raw_fpn_read (file, buf, count, off);
00802 default: return -EINVAL;
00803 }
00804 }
00805
00806 module_init(x353raw_init);
00807 MODULE_LICENSE("GPLv3.0");
00808 MODULE_AUTHOR("Andrey Filippov <andrey@elphel.com>.");
00809 MODULE_DESCRIPTION(IMAGERAW_MODULE_DESCRIPTION);
00810
00811