9afbce54ea33ff58e07a8d6d2cee1a49d2199de6
[people/mcb30/quickusb.git] / kernel / quickusb.c
1 /*
2  * QuickUSB driver
3  *
4  * Copyright 2006 Michael Brown <mbrown@fensystems.co.uk>
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License as
8  * published by the Free Software Foundation; either version 2 of the
9  * License, or (at your option) any later version.
10  *
11  */
12
13 #include <linux/module.h>
14 #include <linux/fs.h>
15 #include <linux/devfs_fs_kernel.h>
16 #include <linux/kref.h>
17 #include <linux/usb.h>
18 #include <asm/uaccess.h>
19 #include "quickusb.h"
20
21 #define QUICKUSB_VENDOR_ID 0x0fbb
22 #define QUICKUSB_DEVICE_ID 0x0001
23
24 #define QUICKUSB_MAX_SUBDEVS 8
25 #define QUICKUSB_SUBDEV_MASK ( QUICKUSB_MAX_SUBDEVS - 1 )
26 #define QUICKUSB_MINOR_BOARD( dev_minor ) \
27         ( (dev_minor) / QUICKUSB_MAX_SUBDEVS )
28 #define QUICKUSB_MINOR_SUBDEV( dev_minor ) \
29         ( (dev_minor) & QUICKUSB_SUBDEV_MASK )
30 #define QUICKUSB_MINOR( board, subdev ) \
31         ( (board) * QUICKUSB_MAX_SUBDEVS + (subdev) )
32
33 #define QUICKUSB_MAX_GPPIO 5
34
35 struct quickusb_gppio {
36         struct quickusb_device *quickusb;
37         unsigned int port;
38 };
39
40 struct quickusb_subdev {
41         struct file_operations *f_op;
42         void *private_data;
43         dev_t dev;
44         unsigned char name[32];
45         struct class_device *class_dev;
46 };
47
48 struct quickusb_device {
49         struct usb_device *usb;
50         struct usb_interface *interface;
51         struct kref kref;
52         struct list_head list;
53         unsigned int board;
54         struct quickusb_gppio gppio[QUICKUSB_MAX_GPPIO];
55         struct quickusb_subdev subdev[QUICKUSB_MAX_SUBDEVS];
56 };
57
58 static void quickusb_delete ( struct kref *kref ) {
59         struct quickusb_device *quickusb;
60
61         quickusb = container_of ( kref, struct quickusb_device, kref );
62         usb_put_dev ( quickusb->usb );
63         kfree ( quickusb );
64 }
65
66 static LIST_HEAD ( quickusb_list );
67
68 static DECLARE_MUTEX ( quickusb_lock );
69
70 static struct class_simple *quickusb_class;
71
72 static int debug = 0;
73 static int dev_major = 0;
74
75 /****************************************************************************
76  *
77  * GPPIO char device operations
78  *
79  */
80
81 static int quickusb_gppio_open ( struct inode *inode, struct file *file ) {
82         struct quickusb_gppio *gppio = file->private_data;
83         unsigned int fmode_rw;
84         int rc;
85
86         fmode_rw = ( file->f_mode & ( FMODE_READ | FMODE_WRITE ) );
87         switch ( fmode_rw ) {
88         case FMODE_READ:
89                 if ( ( rc = quickusb_write_port_dir ( gppio->quickusb->usb,
90                                                       gppio->port,
91                                                       0x00 ) ) != 0 )
92                         return rc;
93                 break;
94         case FMODE_WRITE:
95                 if ( ( rc = quickusb_write_port_dir ( gppio->quickusb->usb,
96                                                       gppio->port,
97                                                       0xff ) ) != 0 )
98                         return rc;
99                 break;
100         default:
101                 /* Do not set port direction; opener must use ioctl to
102                  * set individual bits
103                  */
104                 break;
105         }
106
107         return 0;
108 }
109
110 static ssize_t quickusb_gppio_read ( struct file *file, char __user *user_data,
111                                      size_t len, loff_t *ppos ) {
112         struct quickusb_gppio *gppio = file->private_data;
113         unsigned char data[QUICKUSB_MAX_DATA_LEN];
114         int rc;
115
116         if ( len > sizeof ( data ) )
117                 len = sizeof ( data );
118
119         if ( ( rc = quickusb_read_port ( gppio->quickusb->usb, gppio->port,
120                                          data, &len ) ) != 0 )
121                 return rc;
122
123         if ( ( rc = copy_to_user ( user_data, data, len ) ) != 0 )
124                 return rc;
125
126         *ppos += len;
127         return len;
128 }
129
130 static ssize_t quickusb_gppio_write ( struct file *file,
131                                       const char __user *user_data,
132                                       size_t len, loff_t *ppos ) {
133         struct quickusb_gppio *gppio = file->private_data;
134         unsigned char data[QUICKUSB_MAX_DATA_LEN];
135         int rc;
136
137         if ( len > sizeof ( data ) )
138                 len = sizeof ( data );
139
140         if ( ( rc = copy_from_user ( data, user_data, len ) ) != 0 )
141                 return rc;
142
143         if ( ( rc = quickusb_write_port ( gppio->quickusb->usb, gppio->port,
144                                           data, &len ) ) != 0 )
145                 return rc;
146
147         *ppos += len;
148         return len;
149 }
150
151 static int quickusb_gppio_ioctl ( struct inode *inode, struct file *file,
152                                   unsigned int cmd, unsigned long arg ) {
153         struct quickusb_gppio *gppio = file->private_data;
154         void __user *user_data = ( void __user * ) arg;
155         quickusb_gppio_ioctl_data_t data;
156         unsigned char outputs;
157         int rc;
158
159         if ( ( rc = copy_from_user ( &data, user_data, sizeof (data) ) ) != 0 )
160                 return rc;
161
162         switch ( cmd ) {
163         case QUICKUSB_IOC_GPPIO_GET_OUTPUTS:
164                 if ( ( rc = quickusb_read_port_dir ( gppio->quickusb->usb,
165                                                      gppio->port,
166                                                      &outputs ) ) != 0 )
167                         return rc;
168                 data = outputs;
169                 break;
170         case QUICKUSB_IOC_GPPIO_SET_OUTPUTS:
171                 outputs = data;
172                 if ( ( rc = quickusb_write_port_dir ( gppio->quickusb->usb,
173                                                       gppio->port,
174                                                       outputs ) ) != 0 )
175                         return rc;
176                 break;
177         default:
178                 return -ENOTTY;
179         }
180
181         if ( ( rc = copy_to_user ( user_data, &data, sizeof ( data ) ) ) != 0 )
182                 return rc;
183
184         return 0;
185 }
186
187 static int quickusb_gppio_release ( struct inode *inode, struct file *file ) {
188         struct quickusb_gppio *gppio = file->private_data;
189         
190         kref_put ( &gppio->quickusb->kref, quickusb_delete );
191         return 0;
192 }
193
194 static struct file_operations quickusb_gppio_fops = {
195         .owner          = THIS_MODULE,
196         .open           = quickusb_gppio_open,
197         .read           = quickusb_gppio_read,
198         .write          = quickusb_gppio_write,
199         .ioctl          = quickusb_gppio_ioctl,
200         .release        = quickusb_gppio_release,
201 };
202
203 /****************************************************************************
204  *
205  * Char device (subdev) operations
206  *
207  */
208
209 static int quickusb_open ( struct inode *inode, struct file *file ) {
210         unsigned int board = QUICKUSB_MINOR_BOARD ( iminor ( inode ) );
211         unsigned int subdev = QUICKUSB_MINOR_SUBDEV ( iminor ( inode ) );
212         struct quickusb_device *quickusb;
213         int found = 0;
214         int rc = 0;
215
216         /* Locate board and increase refcount */
217         down ( &quickusb_lock );
218         list_for_each_entry ( quickusb, &quickusb_list, list ) {
219                 if ( quickusb->board == board ) {
220                         kref_get ( &quickusb->kref );
221                         found = 1;
222                         break;
223                 }
224         }
225         up ( &quickusb_lock );
226         if ( ! found ) {
227                 quickusb = NULL;
228                 rc = -ENODEV;
229                 goto out;
230         }
231
232         /* Set up per-subdevice file operations and private data */
233         file->f_op = quickusb->subdev[subdev].f_op;
234         file->private_data = quickusb->subdev[subdev].private_data;
235         if ( ! file->f_op ) {
236                 rc = -ENODEV;
237                 goto out;
238         }
239         
240         /* Perform any subdev-specific open operation */
241         if ( file->f_op->open )
242                 rc = file->f_op->open ( inode, file );
243
244  out:
245         if ( ( rc != 0 ) && quickusb )
246                 kref_put ( &quickusb->kref, quickusb_delete );
247         return rc;
248 }
249
250 static struct file_operations quickusb_fops = {
251         .owner          = THIS_MODULE,
252         .open           = quickusb_open,
253 };
254
255 /****************************************************************************
256  *
257  * Char device (subdev) registration/deregistration
258  *
259  */
260
261 static int quickusb_register_subdev ( struct quickusb_device *quickusb,
262                                       unsigned int subdev_idx,
263                                       struct file_operations *f_op,
264                                       void *private_data,
265                                       const char *subdev_fmt, ... ) {
266         struct quickusb_subdev *subdev = &quickusb->subdev[subdev_idx];
267         struct device *device = &quickusb->interface->dev;
268         unsigned int dev_minor;
269         va_list ap;
270         int rc;
271
272         /* Construct device number */
273         dev_minor = QUICKUSB_MINOR ( quickusb->board, subdev_idx );
274         subdev->dev = MKDEV ( dev_major, dev_minor );
275
276         /* Fill subdev structure */
277         subdev->f_op = f_op;
278         subdev->private_data = private_data;
279
280         /* Construct device name */
281         va_start ( ap, subdev_fmt );
282         vsnprintf ( subdev->name, sizeof ( subdev->name ), subdev_fmt, ap );
283         va_end ( ap );
284
285         /* Create devfs device */
286         if ( ( rc = devfs_mk_cdev ( subdev->dev,
287                                     ( S_IFCHR | S_IRUSR | S_IWUSR |
288                                       S_IRGRP | S_IWGRP ),
289                                     subdev->name ) ) != 0 )
290                 goto err_devfs;
291
292         /* Create class device */
293         subdev->class_dev = class_simple_device_add ( quickusb_class,
294                                                       subdev->dev, device,
295                                                       subdev->name );
296         if ( IS_ERR ( subdev->class_dev ) ) {
297                 rc = PTR_ERR ( subdev->class_dev );
298                 goto err_class;
299         }
300
301         return 0;
302
303  err_class:
304         devfs_remove ( subdev->name );
305  err_devfs:
306         memset ( subdev, 0, sizeof ( *subdev ) );
307         return rc;
308 }
309                                       
310 static void quickusb_deregister_subdev ( struct quickusb_device *quickusb,
311                                          unsigned int subdev_idx ) {
312         struct quickusb_subdev *subdev = &quickusb->subdev[subdev_idx];
313
314         if ( ! subdev->f_op )
315                 return;
316
317         /* Remove class device */
318         class_simple_device_remove ( subdev->dev );
319
320         /* Remove devfs device */
321         devfs_remove ( subdev->name );
322
323         /* Clear subdev structure */
324         memset ( subdev, 0, sizeof ( *subdev ) );
325 }
326
327 /****************************************************************************
328  *
329  * Device creation / destruction
330  *
331  */
332
333 static int quickusb_register_devices ( struct quickusb_device *quickusb ) {
334         unsigned int subdev_idx = 0;
335         struct quickusb_gppio *gppio;
336         unsigned char gppio_char;
337         int i;
338         int rc;
339
340         /* Register GPPIO ports as subdevs */
341         for ( i = 0 ; i < QUICKUSB_MAX_GPPIO ; i++ ) {
342                 gppio = &quickusb->gppio[i];
343                 gppio_char = ( 'a' + gppio->port );
344                 if ( ( rc = quickusb_register_subdev ( quickusb, subdev_idx++,
345                                                        &quickusb_gppio_fops,
346                                                        gppio,
347                                                        "qu%dg%c",
348                                                        quickusb->board,
349                                                        gppio_char ) ) != 0 )
350                         return rc;
351         }
352         
353         return 0;
354 }
355
356 static void quickusb_deregister_devices ( struct quickusb_device *quickusb ) {
357         int i;
358
359         /* Deregister all subdevs */
360         for ( i = 0 ; i < QUICKUSB_MAX_SUBDEVS ; i++ ) {
361                 quickusb_deregister_subdev ( quickusb, i );
362         }
363 }
364
365 /****************************************************************************
366  *
367  * USB hotplug add/remove
368  *
369  */
370
371 static int quickusb_probe ( struct usb_interface *interface,
372                             const struct usb_device_id *id ) {
373         struct quickusb_device *quickusb = NULL;
374         struct quickusb_device *pre_existing_quickusb;
375         unsigned int board = 0;
376         int i;
377         int rc = 0;
378
379         down ( &quickusb_lock );
380
381         /* Create new quickusb device structure */
382         quickusb = kmalloc ( sizeof ( *quickusb ), GFP_KERNEL );
383         if ( ! quickusb ) {
384                 rc = -ENOMEM;
385                 goto err;
386         }
387         memset ( quickusb, 0, sizeof ( *quickusb ) );
388         kref_init ( &quickusb->kref );
389         INIT_LIST_HEAD ( &quickusb_list );
390         quickusb->usb = usb_get_dev ( interface_to_usbdev ( interface ) );
391         quickusb->interface = interface;
392         for ( i = 0 ; i < QUICKUSB_MAX_GPPIO ; i++ ) {
393                 quickusb->gppio[i].quickusb = quickusb;
394                 quickusb->gppio[i].port = i;
395         }
396         
397         /* Obtain a free board board and link into list */
398         list_for_each_entry ( pre_existing_quickusb, &quickusb_list, list ) {
399                 if ( pre_existing_quickusb->board != board )
400                         break;
401                 board++;
402         }
403         quickusb->board = board;
404         list_add_tail ( &quickusb->list, &pre_existing_quickusb->list );
405
406         /* Record driver private data */
407         usb_set_intfdata ( interface, quickusb );
408
409         /* Register devices */
410         if ( ( rc = quickusb_register_devices ( quickusb ) ) != 0 ) {
411                 printk ( KERN_ERR "quickusb unable to register devices\n" );
412                 goto err;
413         }
414
415         printk ( KERN_INFO "quickusb%d connected\n", quickusb->board ); 
416         goto out;
417
418  err:
419         usb_set_intfdata ( interface, NULL );
420         if ( quickusb ) {
421                 quickusb_deregister_devices ( quickusb );
422                 list_del ( &quickusb->list );
423                 kref_put ( &quickusb->kref, quickusb_delete );
424         }
425  out:
426         up ( &quickusb_lock );
427         return rc;
428 }
429
430 static void quickusb_disconnect ( struct usb_interface *interface ) {
431         struct quickusb_device *quickusb = usb_get_intfdata ( interface );
432
433         printk ( KERN_INFO "quickusb%d disconnected\n", quickusb->board );
434
435         down ( &quickusb_lock );
436         usb_set_intfdata ( interface, NULL );
437         quickusb_deregister_devices ( quickusb );
438         list_del ( &quickusb->list );
439         up ( &quickusb_lock );
440
441         kref_put ( &quickusb->kref, quickusb_delete );
442 }
443
444 static struct usb_device_id quickusb_ids[] = {
445         { USB_DEVICE ( QUICKUSB_VENDOR_ID, QUICKUSB_DEVICE_ID ) },
446         { },
447 };
448
449 static struct usb_driver quickusb_driver = {
450         .owner          = THIS_MODULE,
451         .name           = "quickusb",
452         .probe          = quickusb_probe,
453         .disconnect     = quickusb_disconnect,
454         .id_table       = quickusb_ids,
455 };
456
457 /****************************************************************************
458  *
459  * Kernel module interface
460  *
461  */
462
463 static int quickusb_init ( void ) {
464         int rc;
465
466         /* Register major char device */
467         if ( ( rc = register_chrdev ( dev_major, "quickusb",
468                                       &quickusb_fops ) ) < 0 ) {
469                 printk ( KERN_ERR "quickusb could not register char device: "
470                          "error %d\n", rc );
471                 goto err_chrdev;
472         }
473         if ( ! dev_major ) {
474                 dev_major = rc;
475                 printk ( KERN_INFO "quickusb using major device %d\n",
476                          dev_major );
477         }
478         
479         /* Create device class */
480         quickusb_class = class_simple_create ( THIS_MODULE, "quickusb" );
481         if ( IS_ERR ( quickusb_class ) ) {
482                 rc = PTR_ERR ( quickusb_class );
483                 printk ( KERN_ERR "quickusb could not create device class: "
484                          "error %d\n", rc );
485                 goto err_class;
486         }
487
488         if ( ( rc = usb_register ( &quickusb_driver ) ) != 0 )
489                 goto err_usb;
490
491         return 0;
492
493  err_usb:
494         class_simple_destroy ( quickusb_class );
495  err_class:
496         unregister_chrdev ( dev_major, "quickusb" );
497  err_chrdev:
498         return rc;
499 }
500
501 static void quickusb_exit ( void ) {
502         usb_deregister ( &quickusb_driver );
503         class_simple_destroy ( quickusb_class );
504         unregister_chrdev ( dev_major, "quickusb" );
505 }
506
507 module_init ( quickusb_init );
508 module_exit ( quickusb_exit );
509
510 MODULE_AUTHOR ( "Michael Brown <mbrown@fensystems.co.uk>" );
511 MODULE_DESCRIPTION ( "QuickUSB serial driver" );
512 MODULE_LICENSE ( "GPL" );
513 MODULE_DEVICE_TABLE ( usb, quickusb_ids );
514
515 module_param ( debug, bool, S_IRUGO | S_IWUSR );
516 MODULE_PARM_DESC ( debug, "Enable debugging" );
517
518 module_param ( dev_major, uint, S_IRUGO | S_IWUSR );
519 MODULE_PARM_DESC ( dev_major, "Major device number" );