00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00217 #include <linux/init.h>
00218 #include <linux/module.h>
00219 #include <linux/kernel.h>
00220 #include <linux/sched.h>
00221 #include <linux/fs.h>
00222 #include <asm/uaccess.h>
00223 #include <linux/stat.h>
00224 #include <linux/kdev_t.h>
00225 #include <linux/devfs_fs_kernel.h>
00226 #include <linux/slab.h>
00227 #include "dummy.h"
00228
00241 static int dummy_open (struct inode *inode, struct file *file)
00242 {
00243 int minor_lu = -1;
00244 int index = 0;
00245
00246
00247 minor_lu = MINOR(inode->i_rdev);
00248
00249
00250 if (minor_lu > (DeviceCount*2 - 1)) {
00251 DEBUG && printk (KERN_ALERT "peripherique non supporte !\n");
00252 return -ENODEV;
00253 }
00254
00255
00256 if( down_interruptible(&open_critique[minor_lu]) ) {
00257 DEBUG && printk (KERN_ALERT "impossible de prendre le semaphore\n");
00258 return -ERESTARTSYS;
00259 }
00260
00261
00262 if(1 == already_opened[minor_lu]) {
00263 DEBUG && printk (KERN_ALERT "deja ouvert !\n");
00264 up(&open_critique[minor_lu]);
00265 return -EBUSY;
00266 }
00267 already_opened[minor_lu] = 1;
00268
00269
00270 if (0 == minor_lu % 2 && file->f_mode & FMODE_READ) {
00271 DEBUG && printk (KERN_ALERT "ouverture non autorisee en lecture !\n");
00272 up(&open_critique[minor_lu]);
00273 return -EACCES;
00274 }
00275
00276
00277 if (1 == minor_lu % 2 && file->f_mode & FMODE_WRITE) {
00278 DEBUG && printk (KERN_ALERT "ouverture non autorisee en ecriture !\n");
00279 up(&open_critique[minor_lu]);
00280 return -EACCES;
00281 }
00282
00283
00284
00285 if(try_module_get(THIS_MODULE) < 0) {
00286 DEBUG && printk (KERN_ALERT "erreur d'incrementation du compteur d'usage\n");
00287 up(&open_critique[minor_lu]);
00288 return -ERESTARTSYS;
00289 }
00290
00291
00292 index = (int)minor_lu/2;
00293 file->private_data = &device_fifo[index];
00294
00295
00296 up(&open_critique[minor_lu]);
00297
00298 DEBUG && printk (KERN_ALERT "ouverture autorisee !\n");
00299 DEBUG && printk (KERN_ALERT "utilisation de la file %d\n", index);
00300
00301 return 0;
00302 }
00303
00310 static int dummy_release (struct inode *inode, struct file *file)
00311 {
00312 int minor_lu = -1;
00313 int index = 0;
00314
00315
00316 minor_lu = MINOR(inode->i_rdev);
00317 index = (int)minor_lu/2;
00318
00319 DEBUG && printk (KERN_ALERT "fichier special ferme !\n");
00320
00321 if( down_interruptible(&open_critique[minor_lu]) ) {
00322 DEBUG && printk (KERN_ALERT "impossible de prendre le semaphore\n");
00323 return -ERESTARTSYS;
00324 }
00325 already_opened[minor_lu] = 0;
00326
00327 module_put(THIS_MODULE);
00328
00329 up(&open_critique[minor_lu]);
00330
00331 return 0;
00332 }
00333
00345 static ssize_t dummy_write (struct file *file, const char *buffer, size_t size, loff_t *offset)
00346 {
00347 struct private_dummy *private_data = file->private_data;
00348 struct element_fifo *last_element = NULL;
00349 struct element_fifo *new_element = NULL;
00350 struct element_fifo *current_element = NULL;
00351 struct element_fifo *head_element = private_data->head;
00352 size_t count = 0;
00353 size_t total_length = 0;
00354 unsigned long ret_code = 0;
00355 size_t origin_size = size;
00356 size_t retvalue = 0;
00357
00358 if( down_interruptible(&private_data->in_use_critique) ) {
00359 DEBUG && printk (KERN_ALERT "impossible de prendre le semaphore\n");
00360 return -ERESTARTSYS;
00361 }
00362
00363
00364 if (1 == private_data->in_use && O_NONBLOCK & file->f_flags) {
00365 up(&private_data->in_use_critique);
00366 return -EAGAIN;
00367 }
00368 private_data->in_use = 1;
00369 up(&private_data->in_use_critique);
00370
00371
00372 if( down_interruptible(&private_data->rw_critique) ) {
00373 DEBUG && printk (KERN_ALERT "impossible de prendre le semaphore\n");
00374 return -ERESTARTSYS;
00375 }
00376
00377
00378
00379 if(NULL == head_element) {
00380 head_element = kmalloc (sizeof(struct element_fifo), GFP_KERNEL);
00381 if(NULL == head_element) {
00382 DEBUG && printk (KERN_ALERT "allocation ratee");
00383 return -ERESTARTSYS;
00384 }
00385
00386 DEBUG && printk(KERN_ALERT "allocation de l'element de tete\n");
00387
00388 head_element->used_bytes = 0;
00389 head_element->position = 0;
00390 head_element->prev = head_element;
00391 head_element->next = head_element;
00392
00393 private_data->head = head_element;
00394 }
00395
00396
00397 while(total_length < origin_size) {
00398
00399 current_element = head_element->prev;
00400
00401
00402 if (size < BUF_SIZE - current_element->used_bytes) {
00403 count = size;
00404 } else {
00405
00406 count = BUF_SIZE - current_element->used_bytes;
00407 }
00408
00409
00410 ret_code = copy_from_user(current_element->buffer + current_element->used_bytes,
00411 buffer, count);
00412
00413 if (0 != ret_code) {
00414 DEBUG && printk(KERN_ALERT "erreur d'ecriture\n");
00415 retvalue = -EFAULT;
00416 goto ret_write;
00417 }
00418
00419 DEBUG && printk(KERN_ALERT "ecriture de %d octets sur %d\n", (int)count,
00420 (int)size);
00421
00422
00423 buffer = buffer + count;
00424
00425 size = size - count;
00426
00427 total_length = total_length + count;
00428 current_element->used_bytes = count + current_element->used_bytes;
00429
00430 DEBUG && printk(KERN_ALERT
00431 "occupation du noeud %d octets sur %d dans la file %d\n",
00432 current_element->used_bytes, BUF_SIZE, private_data->index);
00433
00434 if (BUF_SIZE == current_element->used_bytes) {
00435
00436 new_element = kmalloc (sizeof(struct element_fifo), GFP_KERNEL);
00437 if (new_element == NULL) {
00438 DEBUG && printk (KERN_ALERT "allocation ratee");
00439 retvalue = -ERESTARTSYS;
00440 goto ret_write;
00441 }
00442
00443
00444 last_element = head_element->prev;
00445 last_element->next = new_element;
00446 head_element->prev = new_element;
00447
00448
00449 new_element->used_bytes = 0;
00450 new_element->position = 0;
00451 new_element->prev = last_element;
00452 new_element->next = head_element;
00453
00454 DEBUG && printk(KERN_ALERT "allocation d'un nouveau element\n");
00455 }
00456
00457
00458 schedule();
00459 }
00460 retvalue = total_length;
00461
00462 ret_write:
00463
00464 up(&private_data->rw_critique);
00465
00466 if( down_interruptible(&private_data->in_use_critique) ) {
00467 DEBUG && printk (KERN_ALERT "impossible de prendre le semaphore\n");
00468 return -ERESTARTSYS;
00469 }
00470 private_data->in_use = 0;
00471 up(&private_data->in_use_critique);
00472
00473 return retvalue;
00474 }
00475
00484 static ssize_t dummy_read (struct file *file, char *buffer, size_t size, loff_t *offset)
00485 {
00486 struct private_dummy *private_data = file->private_data;
00487 struct element_fifo *head_element = private_data->head;
00488 struct element_fifo *current_element = NULL;
00489 struct element_fifo *next_element = NULL;
00490 struct element_fifo *prev_element = NULL;
00491 size_t count = 0;
00492 size_t total_length = 0;
00493 unsigned long ret_code = 0;
00494 size_t origin_size = size;
00495 size_t retvalue = 0;
00496
00497 if( down_interruptible(&private_data->in_use_critique) ) {
00498 DEBUG && printk (KERN_ALERT "impossible de prendre le semaphore\n");
00499 return -ERESTARTSYS;
00500 }
00501
00502
00503 if (1 == private_data->in_use && O_NONBLOCK & file->f_flags) {
00504 up(&private_data->in_use_critique);
00505 return -EAGAIN;
00506 }
00507
00508 private_data->in_use = 1;
00509
00510 up(&private_data->in_use_critique);
00511
00512
00513 if( down_interruptible(&private_data->rw_critique) ) {
00514 DEBUG && printk (KERN_ALERT "impossible de prendre le semaphore\n");
00515 return -ERESTARTSYS;
00516 }
00517
00518
00519 while(total_length < origin_size && NULL != head_element) {
00520 current_element = head_element;
00521
00522
00523 if (size < current_element->used_bytes) {
00524 count = size;
00525 } else {
00526 count = current_element->used_bytes;
00527 }
00528
00529
00530 ret_code = copy_to_user(buffer,
00531 current_element->buffer+current_element->position,
00532 count);
00533
00534 if (0 != ret_code) {
00535 DEBUG && printk(KERN_ALERT "erreur de lecture\n");
00536 retvalue = -EFAULT;
00537 goto ret_read;
00538 }
00539
00540 DEBUG && printk(KERN_ALERT "lecture de %d octets sur %d\n", (int)count,
00541 (int)size);
00542
00543
00544 buffer = buffer + count;
00545 size = size - count;
00546 total_length = total_length + count;
00547 current_element->used_bytes = current_element->used_bytes - count;
00548 current_element->position = current_element->position + count;
00549 DEBUG && printk(KERN_ALERT
00550 "occupation du noeud %d octets sur %d dans la file %d\n",
00551 current_element->used_bytes, BUF_SIZE, private_data->index);
00552
00553
00554 if(0 == current_element->used_bytes) {
00555 prev_element = current_element->prev;
00556 next_element = current_element->next;
00557
00558 prev_element->next = next_element;
00559 next_element->prev = prev_element;
00560
00561 if(current_element != current_element->next) {
00562 head_element = next_element;
00563 } else {
00564 head_element = NULL;
00565 }
00566
00567 private_data->head = head_element;
00568
00569 kfree(current_element);
00570 current_element = NULL;
00571 }
00572
00573
00574 schedule();
00575 }
00576 retvalue = total_length;
00577
00578 ret_read:
00579
00580 up(&private_data->rw_critique);
00581
00582 if( down_interruptible(&private_data->in_use_critique) ) {
00583 DEBUG && printk (KERN_ALERT "impossible de prendre le semaphore\n");
00584 return -ERESTARTSYS;
00585 }
00586 private_data->in_use = 0;
00587 up(&private_data->in_use_critique);
00588
00589 return retvalue;
00590 }
00591
00600 static int dummy_init(void)
00601 {
00602 int result;
00603 int i;
00604
00605
00606 result = register_chrdev(DUMMY_MAJOR, DeviceName, &dummy_fops);
00607 if (result < 0) {
00608 DEBUG && printk(KERN_ALERT "majeur %d indisponible\n", result);
00609 return -ERESTARTSYS;
00610 }
00611
00612 if (0 == dummy_major) {
00613 dummy_major = result;
00614 }
00615
00616
00617 for (i = 0; i < DeviceCount; i++) {
00618
00619 devfs_mk_cdev(MKDEV(dummy_major, 2*i), S_IFCHR|S_IRUGO|S_IWUGO, "%s_W%d",
00620 DeviceName, i);
00621 DEBUG && printk(KERN_ALERT "%s_R%d cree\n", DeviceName, i);
00622
00623
00624 devfs_mk_cdev(MKDEV(dummy_major, 2*i+1), S_IFCHR|S_IRUGO|S_IWUGO, "%s_R%d",
00625 DeviceName, i);
00626 DEBUG && printk(KERN_ALERT "%s_W%d cree\n", DeviceName, i);
00627 }
00628
00629
00630 already_opened = kmalloc (DeviceCount*2*sizeof(int), GFP_KERNEL);
00631 if (already_opened == NULL) {
00632 DEBUG && printk (KERN_ALERT "allocation ratee");
00633 return -ERESTARTSYS;
00634 }
00635
00636
00637 open_critique = kmalloc (DeviceCount*2*sizeof(struct semaphore), GFP_KERNEL);
00638 if (open_critique == NULL) {
00639 DEBUG && printk (KERN_ALERT "allocation ratee");
00640 kfree(already_opened);
00641 return -ERESTARTSYS;
00642 }
00643
00644
00645
00646 for(i = 0; i < DeviceCount*2 ; i++) {
00647 already_opened[i] = 0;
00648 sema_init(&open_critique[i], 1);
00649 }
00650
00651
00652 device_fifo = kmalloc (DeviceCount*sizeof(struct private_dummy), GFP_KERNEL);
00653 if(NULL == device_fifo) {
00654 DEBUG && printk (KERN_ALERT "allocation ratee");
00655 kfree(already_opened);
00656 kfree(open_critique);
00657 return -ERESTARTSYS;
00658 }
00659
00660 for(i = 0; i < DeviceCount; i++) {
00661 device_fifo[i].index = i;
00662 device_fifo[i].head = NULL;
00663 device_fifo[i].in_use = 0;
00664 sema_init(&device_fifo[i].in_use_critique, 1);
00665 sema_init(&device_fifo[i].rw_critique, 1);
00666 }
00667
00668 DEBUG && printk(KERN_ALERT "module %s charge gerant 2x%d peripheriques\n", DeviceName,
00669 DeviceCount);
00670
00671
00672
00673 return 0;
00674 }
00675
00682 static void dummy_cleanup(void)
00683 {
00684 int i = 0;
00685 int result;
00686 struct element_fifo *tmp_element = NULL;
00687 struct element_fifo *current_element = NULL;
00688
00689
00690 kfree(open_critique);
00691 open_critique = NULL;
00692
00693 kfree(already_opened);
00694 already_opened = NULL;
00695
00696
00697 for (i = 0; i < DeviceCount; i++) {
00698
00699 current_element = device_fifo[i].head;
00700
00701 if(NULL != current_element) {
00702
00703 while(current_element != current_element->next) {
00704
00705 tmp_element = current_element->next;
00706
00707
00708 tmp_element->prev = current_element->prev;
00709 current_element->prev->next = tmp_element;
00710
00711
00712 kfree(current_element);
00713 current_element = NULL;
00714
00715
00716 current_element = tmp_element;
00717 DEBUG && printk (KERN_ALERT "supression d'un noeud !\n");
00718 }
00719
00720
00721 kfree(current_element);
00722 current_element = NULL;
00723
00724 DEBUG && printk (KERN_ALERT "supression d'un noeud !\n");
00725 }
00726 }
00727
00728
00729 kfree(device_fifo);
00730 device_fifo = NULL;
00731
00732
00733 for (i = 0; i < DeviceCount; i++) {
00734 devfs_remove("%s_R%d", DeviceName, i);
00735 DEBUG && printk(KERN_ALERT "%s_R%d supprime\n", DeviceName, i);
00736
00737 devfs_remove("%s_W%d", DeviceName, i);
00738 DEBUG && printk(KERN_ALERT "%s_W%d supprime\n", DeviceName, i);
00739 }
00740
00741
00742 result = unregister_chrdev(dummy_major, "dummy");
00743 if (result < 0) {
00744 DEBUG && printk (KERN_ALERT "desenregistrement %d rate\n", dummy_major);
00745 return;
00746 }
00747
00748 DEBUG && printk(KERN_ALERT "dummy decharge\n");
00749 }
00750
00751 module_init(dummy_init);
00752 module_exit(dummy_cleanup);
00753
00754 MODULE_PARM (DeviceCount, "i");
00755 MODULE_PARM (DeviceName, "s");