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