AlcapDAQ  1
CAENUSBdrvB.c
Go to the documentation of this file.
1 
2 /*
3  * CAEN USB driver - 1.1
4  *
5  * Written by CAEN SpA (support.computing@caen.it) - CAEN SpA
6  *
7  * based on rio500.c by Cesar Miquel (miquel@df.uba.ar)
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License as
11  * published by the Free Software Foundation; either version 2 of the
12  * License, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful, but
15  * WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  * General Public License for more details.
18  *
19  */
20 
21 #undef DEBUG
22 
23 #include <linux/module.h>
24 #include <linux/kernel.h>
25 #include <linux/signal.h>
26 #include <linux/sched.h>
27 #include <linux/errno.h>
28 #include <linux/random.h>
29 #include <linux/poll.h>
30 #include <linux/init.h>
31 #include <linux/slab.h>
32 #include <linux/spinlock.h>
33 #include <linux/usb.h>
34 #ifdef CONFIG_DEVFS_FS
35 #include <linux/devfs_fs_kernel.h>
36 #endif
37 
38 /*
39  * Version Information
40  */
41 #define DRIVER_VERSION "1.2"
42 #define DRIVER_AUTHOR "CAEN Computing Division <support.computing@caen.it>"
43 #define DRIVER_DESC "CAEN USB driver"
44 
45 #define V1718_MINOR_BASE 178
46 
47 /* stall/wait timeout for V1718 */
48 #define NAK_TIMEOUT (HZ)
49 
50 #define IBUF_SIZE 0x10000 /* 64 kbytes */
51 
52 /* Size of the V1718 buffer */
53 #define OBUF_SIZE 0x10000 /* 64 kbytes */
54 
55 /* we can have up to this number of devices plugged in at once */
56 #define MAX_DEVICES 16
57 //
58 // Rev 0.2: added ini
59 #include <linux/version.h>
60 
61 #ifndef VERSION
62  #define VERSION(ver,rel,seq) (((ver)<<16) | ((rel)<<8) | (seq))
63 #endif
64 
65 #if LINUX_VERSION_CODE >= VERSION(2,5,0)
66  #define USB_ST_NOERROR 0
67  #define USB_ST_CRC (-EILSEQ)
68  #define USB_ST_BITSTUFF (-EPROTO)
69  #define USB_ST_DATAOVERRUN (-EOVERFLOW)
70  #define USB_ST_DATAUNDERRUN (-EREMOTEIO)
71  #define USB_ST_BUFFEROVERRUN (-ECOMM)
72  #define USB_ST_BUFFERUNDERRUN (-ENOSR)
73  #define USB_ST_INTERNALERROR (-EPROTO) /* unknown error */
74  #define USB_ST_SHORT_PACKET (-EREMOTEIO)
75  #define USB_ST_PARTIAL_ERROR (-EXDEV) /* ISO transfer only parti ally completed */
76  #define USB_ST_URB_KILLED (-ENOENT) /* URB canceled by user */
77  #define USB_ST_URB_PENDING (-EINPROGRESS)
78  #define USB_ST_REMOVED (-ENODEV) /* device not existing or removed */
79  #define USB_ST_TIMEOUT (-ETIMEDOUT) /* communication timed out, also in urb->status**/
80  #define USB_ST_NOTSUPPORTED (-ENOSYS)
81  #define USB_ST_BANDWIDTH_ERROR (-ENOSPC) /* too much bandwidth used */
82  #define USB_ST_URB_INVALID_ERROR (-EINVAL) /* invalid value/transfer type */
83  #define USB_ST_URB_REQUEST_ERROR (-ENXIO) /* invalid endpoint */
84  #define USB_ST_STALL (-EPIPE) /* pipe stalled, also in urb->status*/
85 #else
86  #error ######################################################
87  #error ######################################################
88  #error THIS DRIVER NOT IS COMPATIBLE WITH YOUR KERNEL VERSION
89  #error ######################################################
90  #error ######################################################
91 #endif
92 
93 // Rev. 0.4
94 #if LINUX_VERSION_CODE >= VERSION(2,6,11)
95  #include <linux/mutex.h> // for unlocked ioctl interface
96 #endif
97 
98 #if defined(CONFIG_KERNEL_LOCK) || LINUX_VERSION_CODE < VERSION(2,6,38)
99 #include <linux/smp_lock.h>
100 #endif
101 
102 #include "CAENUSBdrvB.h"
103 //
104 // Rev 0.2: added end
105 
107  struct usb_device *v1718_dev; /* init: probe_v1718 */
108  unsigned int ifnum; /* Interface number of the USB device */
109  int open_count; /* number of users */
110  int present; /* Device is present on the bus */
111  int minor; /* minor number for the device */
112  char *obuf, *ibuf; /* transfer buffers */
113  char bulk_in_ep, bulk_out_ep; /* Endpoint assignments */
114  wait_queue_head_t wait_q; /* for timeouts */
115  struct semaphore lock; /* general race avoidance */
116 // Rev 0.4
117 #if LINUX_VERSION_CODE >= VERSION(2,6,11)
118  struct mutex ioctl_lock;
119 #endif
120 };
121 
122 /* array of pointers to our devices that are currently connected */
124 
125 /* lock to protect the minor_table structure */
126 #if LINUX_VERSION_CODE <= VERSION(2,6,35)
127 static DECLARE_MUTEX (minor_table_mutex);
128 #else
129 static DEFINE_SEMAPHORE (minor_table_mutex);
130 #endif
131 
132 static void v1718_delete(struct v1718_usb_data *v1718)
133 {
134 #ifndef CONFIG_USB_DYNAMIC_MINORS
135  minor_table[v1718->minor] = NULL;
136 #else
137  int i = 0;
138  for (; i < MAX_DEVICES; i++) if (v1718->minor == minor_table[i]->minor) break;
139  if (i < MAX_DEVICES) minor_table[i] = NULL;
140 #endif
141  if( v1718->ibuf != NULL )
142  kfree(v1718->ibuf);
143  if( v1718->obuf != NULL )
144  kfree(v1718->obuf);
145  kfree(v1718);
146 }
147 
148 
149 #if LINUX_VERSION_CODE >= VERSION(2,6,11)
150 static long unlocked_ioctl_v1718(struct file *, unsigned int, unsigned long);
151 #endif
152 
153 static int open_v1718(struct inode *inode, struct file *file)
154 {
155  struct v1718_usb_data *v1718 = NULL;
156  int subminor;
157 
158 #ifndef CONFIG_USB_DYNAMIC_MINORS
159  subminor = MINOR(inode->i_rdev) - V1718_MINOR_BASE;
160 #else
161  for (subminor=0; subminor<MAX_DEVICES; subminor++) if (MINOR(inode->i_rdev) == minor_table[subminor]->minor) break;
162 #endif
163 
164  if( (subminor < 0) || (subminor > MAX_DEVICES) )
165  return -ENODEV;
166 
167  down(&minor_table_mutex);
168 
169  v1718 = minor_table[subminor];
170  if( v1718 == NULL ) {
171  up(&minor_table_mutex);
172  return -ENODEV;
173  }
174 
175  down(&v1718->lock);
176 
177  up(&minor_table_mutex);
178 
179  v1718->open_count++;
180 
181  init_waitqueue_head(&v1718->wait_q);
182 
183 
184 #if LINUX_VERSION_CODE >= VERSION(2,6,11)
185  mutex_init(&v1718->ioctl_lock);
186 #endif
187  file->private_data = v1718;
188  up(&v1718->lock);
189 
190  return 0;
191 }
192 
193 static int close_v1718(struct inode *inode, struct file *file)
194 {
195  struct v1718_usb_data *v1718 = (struct v1718_usb_data *)file->private_data;
196  int retval = 0;
197  if( v1718 == NULL ) {
198  printk("Close: object is null\n");
199  return -ENODEV;
200  }
201  down(&minor_table_mutex);
202  down(&v1718->lock);
203 
204  if( v1718->open_count <= 0 ) {
205  printk("Device not opened\n");
206  retval = -ENODEV;
207  goto exit_not_opened;
208  }
209 
210  if( v1718->v1718_dev == NULL ) {
211  /* the device was unplugged before the file was released */
212  up(&v1718->lock);
213  v1718_delete(v1718);
214  up(&minor_table_mutex);
215  return 0;
216  }
217 
218  v1718->open_count--;
219 
220 exit_not_opened:
221  up(&(v1718->lock));
222  up(&minor_table_mutex);
223 
224  return retval;
225 }
226 
227 static int
228 ioctl_v1718(struct inode *inode, struct file *file, unsigned int cmd,
229  unsigned long arg)
230 {
231 
232 
233  int ret= 0;
234  struct v1718_usb_data *v1718;
235 
236  v1718 = (struct v1718_usb_data *)file->private_data;
237  down(&(v1718->lock));
238  /* Sanity check to make sure v1718 is connected, powered, etc */
239  if ( v1718 == NULL ||
240  v1718->present == 0 ||
241  v1718->v1718_dev == NULL )
242  {
243  up(&(v1718->lock));
244  return -ENOTTY;
245  }
246 
247  switch (cmd) {
248  case V1718_IOCTL_REV:
249  {
250  v1718_rev_t rev;
251  if( copy_from_user(&rev, (v1718_rev_t *)arg, sizeof(rev)) > 0 ) {
252  ret = -EFAULT;
253  break;
254  }
255  strcpy( rev.rev_buf, DRIVER_VERSION);
256  if( copy_to_user((v1718_rev_t *)arg, &rev, sizeof(rev)) > 0) {
257  ret = -EFAULT;
258  break;
259  }
260  }
261  break;
262  case V1718_IOCTL_REBOOTB:
263  ret = usb_control_msg(v1718->v1718_dev, usb_sndctrlpipe(v1718->v1718_dev,0),0xB0, 0x20,1, 0, NULL, 0, 1 * HZ);
264  ret |= usb_control_msg(v1718->v1718_dev, usb_sndctrlpipe(v1718->v1718_dev,0),0xB0, 0x20,0, 0, NULL, 0, 1 * HZ);
265  break;
266  case V1718_IOCTL_REBOOTF:
267  ret = usb_control_msg(v1718->v1718_dev, usb_sndctrlpipe(v1718->v1718_dev,0),0xB0, 0x20,3, 0, NULL, 0, 1 * HZ);
268  ret |= usb_control_msg(v1718->v1718_dev, usb_sndctrlpipe(v1718->v1718_dev,0),0xB0, 0x20,2, 0, NULL, 0, 1 * HZ);
269  break;
270  default:
271  ret= -ENOTTY;
272  break;
273  }
274  up(&(v1718->lock));
275  return ret;
276 }
277 
278 
279 /*
280  ----------------------------------------------------------------------
281 
282  unlocked_ioctl_v1718 (Called in preference to ioctl_v1718 on newer kernels)
283 
284  ----------------------------------------------------------------------
285 */
286 
287 #if LINUX_VERSION_CODE >= VERSION(2,6,11)
288 static long unlocked_ioctl_v1718(struct file *file, unsigned int cmd, unsigned long arg)
289 {
290  struct inode *inode = file->f_dentry->d_inode;
291  struct v1718_usb_data *s = (struct v1718_usb_data *)file->private_data;
292  long ret;
293 
294  /* ioctl() calls can cause the Big Kernel Lock (BKL) to be taken, which
295  * can have significant performance penalties system-wide. By providing
296  * an unlocked ioctl() method the BKL will not be taken, but the driver
297  * becomes responsible for its own locking. Furthermore, the lock can be
298  * broken down per A2818 so that multiple threads accessing different CONET
299  * chains do not contend with one another during ioctl() calls.
300  */
301  mutex_lock(&s->ioctl_lock);
302  ret = (long) ioctl_v1718(inode, file, cmd, arg);
303  mutex_unlock(&s->ioctl_lock);
304 
305  return ret;
306 }
307 #endif
308 
309 static ssize_t
310 write_v1718(struct file *file, const char *buffer,
311  size_t count, loff_t * ppos)
312 {
313  struct v1718_usb_data *v1718;
314 
315  unsigned long copy_size;
316  unsigned long bytes_written = 0;
317  unsigned int partial;
318 
319  int result = 0;
320  int maxretry;
321  int errn = 0;
322 
323  v1718 = (struct v1718_usb_data *)file->private_data;
324 
325  down(&(v1718->lock));
326  /* Sanity check to make sure v1718 is connected, powered, etc */
327  if ( v1718 == NULL ||
328  v1718->present == 0 ||
329  v1718->v1718_dev == NULL )
330  {
331  up(&(v1718->lock));
332  return -ENODEV;
333  }
334 
335  do {
336  unsigned long thistime;
337  char *obuf = v1718->obuf;
338 
339  thistime = copy_size =
340  (count >= OBUF_SIZE) ? OBUF_SIZE : count;
341  if (copy_from_user(v1718->obuf, buffer, copy_size)) {
342  errn = -EFAULT;
343  goto error;
344  }
345  maxretry = 1;
346  while (thistime) {
347  if (!v1718->v1718_dev) {
348  errn = -ENODEV;
349  goto error;
350  }
351  if (signal_pending(current)) {
352  up(&(v1718->lock));
353  return bytes_written ? bytes_written : -EINTR;
354  }
355 
356  result = usb_bulk_msg(v1718->v1718_dev,
357  usb_sndbulkpipe(v1718->v1718_dev, 2),
358  obuf, thistime, &partial, 1 * HZ); // TEMP - 1 sec basta?
359 
360  dbg("write stats: result:%d thistime:%lu partial:%u",
361  result, thistime, partial);
362 
363  if (result == USB_ST_TIMEOUT) {
364  if (!maxretry--) {
365  errn = -ETIME;
366  goto error;
367  }
368 
369  wait_event_interruptible_timeout(v1718-> wait_q,(result == USB_ST_TIMEOUT),NAK_TIMEOUT);
370  continue;
371  } else if (!result && partial) {
372  obuf += partial;
373  thistime -= partial;
374  } else
375  break;
376  };
377  if (result) {
378  printk("Write Whoops - %x\n", result);
379  errn = -EIO;
380  goto error;
381  }
382  bytes_written += copy_size;
383  count -= copy_size;
384  buffer += copy_size;
385  } while (count > 0);
386 
387  up(&(v1718->lock));
388 
389  return bytes_written ? bytes_written : -EIO;
390 
391 error:
392  up(&(v1718->lock));
393  return errn;
394 }
395 
396 static ssize_t
397 read_v1718(struct file *file, char *buffer, size_t count, loff_t * ppos)
398 {
399  struct v1718_usb_data *v1718;
400  ssize_t read_count;
401  unsigned int partial;
402  int this_read;
403  int result;
404  int maxretry = 1;
405  char *ibuf;
406 
407  v1718 = (struct v1718_usb_data *)file->private_data;
408 
409  down(&(v1718->lock));
410  /* Sanity check to make sure v1718 is connected, powered, etc */
411  if ( v1718 == NULL ||
412  v1718->present == 0 ||
413  v1718->v1718_dev == NULL )
414  {
415  up(&(v1718->lock));
416  return -ENODEV;
417  }
418 
419  ibuf = v1718->ibuf;
420 
421  read_count = 0;
422 
423  while (count > 0) {
424 
425  if (!v1718->v1718_dev) {
426  up(&(v1718->lock));
427  return -ENODEV;
428  }
429  this_read = (count >= IBUF_SIZE) ? IBUF_SIZE : count;
430 
431  result = usb_bulk_msg(v1718->v1718_dev,
432  usb_rcvbulkpipe(v1718->v1718_dev, 6),
433  ibuf, this_read, &partial,
434  (int) (HZ * 1));
435 
436  dbg("read stats: result:%d this_read:%u partial:%u",
437  result, this_read, partial);
438  if (partial) {
439  count = this_read = partial;
440  } else {
441  switch( result){
442  case USB_ST_BUFFERUNDERRUN:
443  printk( "DBG read_v1718 USB_ST_BUFFERUNDERRUN ...\n" );
444  usb_clear_halt( v1718->v1718_dev, 6);
445  up(&(v1718->lock));
446  return (0);
447  case USB_ST_TIMEOUT:
448  case 15:
449  if (!maxretry--) {
450  up(&(v1718->lock));
451  printk("read: maxretry timeout\n");
452  return -ETIME;
453  }
454 
455  wait_event_interruptible_timeout(v1718-> wait_q,1,NAK_TIMEOUT);
456  this_read= 0;
457  break;
458  case USB_ST_DATAOVERRUN:
459  {
460  int count_retry= 100;
461  do {
462  printk( "DATAOVERRUN\n");
463  usb_clear_halt( v1718->v1718_dev, 6);
464  if( usb_bulk_msg(v1718->v1718_dev,
465  usb_rcvbulkpipe(v1718->v1718_dev, 6),
466  ibuf, IBUF_SIZE, &partial,
467  (int) (HZ * 1))!= USB_ST_DATAOVERRUN){
468  break;
469  }
470  } while( count_retry--);
471  }
472  up(&(v1718->lock));
473  return -EIO;
474  case USB_ST_SHORT_PACKET:
475  case USB_ST_PARTIAL_ERROR:
476  case USB_ST_URB_KILLED:
477  case USB_ST_URB_PENDING:
478  case USB_ST_REMOVED:
479  case USB_ST_CRC:
480  case USB_ST_BITSTUFF:
481  case USB_ST_BUFFEROVERRUN:
482  case USB_ST_NOTSUPPORTED:
483  case USB_ST_BANDWIDTH_ERROR:
484  case USB_ST_URB_INVALID_ERROR:
485  case USB_ST_URB_REQUEST_ERROR:
486  case USB_ST_STALL:
487  default:
488  usb_clear_halt( v1718->v1718_dev, 6);
489  up(&(v1718->lock));
490  printk("Read Whoops - result:0x%08x partial:%u this_read:%u\n",
491  result, partial, this_read);
492  return -EIO;
493  }
494  }
495  if (this_read) {
496  if (copy_to_user(buffer, ibuf, this_read)) {
497  up(&(v1718->lock));
498  return -EFAULT;
499  }
500  count -= this_read;
501  read_count += this_read;
502  buffer += this_read;
503  }
504  }
505  up(&(v1718->lock));
506  return read_count;
507 }
508 
509 static struct
510 file_operations usb_v1718_fops = {
511  owner: THIS_MODULE,
512  read: read_v1718,
513  write: write_v1718,
514 #if LINUX_VERSION_CODE < VERSION(2,6,38)
515  ioctl: ioctl_v1718,
516 #endif
517 // Rev. 0.4
518 #if LINUX_VERSION_CODE >= VERSION(2,6,11)
519  unlocked_ioctl: unlocked_ioctl_v1718,
520 #endif
521  open: open_v1718,
522  release: close_v1718,
523 };
524 
525 static struct usb_class_driver usb_v1718_class = {
526  .name = "usb/v1718_%d",
527  .fops = &usb_v1718_fops ,
528 #if LINUX_VERSION_CODE <= VERSION(2,6,13)
529  .mode = S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP ,
530 #endif
531  .minor_base = V1718_MINOR_BASE ,
532 };
533 
534 static int probe_v1718(struct usb_interface *intf,
535  const struct usb_device_id *id)
536 {
537  struct usb_device *dev = interface_to_usbdev(intf);
538  int retval= 0;
539  struct v1718_usb_data *v1718 = NULL;
540 // Rev 0.2
541 // char name[12];
542  int minor;
543  switch(id->idProduct) {
544  case 0x0000:
545  printk(KERN_INFO "CAEN Desktop Waveform Digitizers Carrier found at address %d\n", dev->devnum);
546  break;
547  case 0x0001:
548  printk(KERN_INFO "CAEN NIM Waveform Digitizers Carrier found at address %d\n", dev->devnum);
549  break;
550  case 0x1002:
551  printk(KERN_INFO "CAEN V1718 found at address %d\n", dev->devnum);
552  break;
553  default:
554  printk(KERN_INFO "CAEN V1718 found at address %d\n", dev->devnum);
555  break;
556  }
557  down(&minor_table_mutex);
558  for( minor = 0; minor < MAX_DEVICES; ++minor ) {
559  if( minor_table[minor] == NULL )
560  break;
561  }
562  if( minor >= MAX_DEVICES ) {
563  printk(KERN_INFO "Too many devices\n");
564  goto exit;
565  }
566 
567  v1718 = kmalloc(sizeof(struct v1718_usb_data), GFP_KERNEL);
568  if (v1718 == NULL) {
569  printk("Out of memory\n");
570  goto exit;
571  }
572  memset(v1718, 0x00, sizeof(*v1718));
573  minor_table[minor] = v1718;
574 
575  if( usb_register_dev(intf, &usb_v1718_class))
576  {
577  printk("probe: Not able to get a minor for this device.\n");
578  goto error;
579  }
580 #ifdef CONFIG_USB_DYNAMIC_MINORS
581  minor = intf->minor;
582 #endif
583  v1718->present = 1;
584  v1718->v1718_dev = dev;
585  v1718->minor = minor;
586 
587  if (!(v1718->obuf = (char *) kmalloc(OBUF_SIZE, GFP_KERNEL))) {
588  printk("probe: Not enough memory for the output buffer\n");
589  goto error;
590  }
591  dbg("probe: obuf address:%p", v1718->obuf);
592 
593  if (!(v1718->ibuf = (char *) kmalloc(IBUF_SIZE, GFP_KERNEL))) {
594  printk("probe: Not enough memory for the input buffer\n");
595  goto error;
596  }
597  dbg("probe: ibuf address:%p", v1718->ibuf);
598 
599  usb_set_intfdata (intf, v1718);
600 #if LINUX_VERSION_CODE <= VERSION(2,6,32)
601  init_MUTEX(&(v1718->lock));
602 #else
603  sema_init(&(v1718->lock),1);
604 #endif
605  goto exit;
606 
607 error:
608  usb_deregister_dev(intf, &usb_v1718_class);
609  retval= -ENOMEM;
610  v1718_delete(v1718);
611  v1718 = NULL;
612 
613 exit:
614  up(&minor_table_mutex);
615  return retval;
616 
617 }
618 
619 static void disconnect_v1718(struct usb_interface *intf)
620 {
621  struct v1718_usb_data *v1718 = usb_get_intfdata (intf);
622 
623  int minor;
624 
625  down(&minor_table_mutex);
626  down(&(v1718->lock));
627 
628  minor = v1718->minor;
629 
630  usb_set_intfdata (intf, NULL);
631  if (v1718) {
632  usb_deregister_dev(intf, &usb_v1718_class);
633  if (v1718->open_count != 0) {
634  /* better let it finish - the release will do whats needed */
635  v1718->v1718_dev = NULL;
636  up(&(v1718->lock));
637  } else {
638  up(&(v1718->lock));
639  v1718_delete(v1718);
640  }
641  }
642 
643 
644  printk(KERN_INFO "CAEN #%d device disconnected\n", minor);
645 
646  up(&minor_table_mutex);
647 }
648 
649 static struct usb_device_id v1718_table [] = {
650  { USB_DEVICE(0x0547, 0x1002) }, /* CAEN V1718 */
651  { USB_DEVICE(0x21e1, 0x0000) },
652  { USB_DEVICE(0x21e1, 0x0001) },
653  { } /* Terminating entry */
654 };
655 
656 MODULE_DEVICE_TABLE (usb, v1718_table);
657 
658 // Rev 0.4
659 static struct usb_driver v1718_driver = {
660 #if LINUX_VERSION_CODE < VERSION(2,6,15)
661  owner: THIS_MODULE,
662 #endif
663  name: "v1718",
665  disconnect: disconnect_v1718,
666  id_table: v1718_table,
667 };
668 
669 static int __init usb_v1718_init(void)
670 
671 {
672  if (usb_register(&v1718_driver) < 0)
673  return -1;
674  printk(DRIVER_DESC " version " DRIVER_VERSION "\n");
675 
676  return 0;
677 }
678 
679 static void __exit usb_v1718_cleanup(void)
680 
681 {
682  usb_deregister(&v1718_driver);
683 }
684 
687 
690 MODULE_LICENSE("GPL");
691