Subversion Repositories f9daq

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
6 f9daq 1
/************************************************************************\
2
##                                                                      ##
3
##  Creation Date: 17 Mar 2007                                          ##
4
##  Last Update:   18 Mar 2007                                          ##
5
##  Author:       XInstruments                                          ##
6
##                                                                      ##
7
\************************************************************************/
8
 
9
 
10
#include        <linux/kernel.h>
11
#include        <linux/init.h>
12
#include        <linux/module.h>
13
#include        <linux/usb.h>
14
#include        <asm/uaccess.h>
15
#include        "usmcdrv-driver.h"
16
#include        "usmctypes.h"
17
#include        "usmcpkt.h"
18
 
19
#include <linux/slab.h>
20
 
21
#if HAVE_UNLOCKED_IOCTL
22
    #include <linux/mutex.h>
23
#else
24
    #include <linux/smp_lock.h>
25
#endif
26
#define  info( format, arg...) printk(KERN_INFO  USMC_DEV_NAME ": " format "\n", ## arg) 
27
#define  err( format, arg...) printk(KERN_ERR  USMC_DEV_NAME ": " format "\n", ## arg) 
28
 
29
 
30
 
31
MODULE_DESCRIPTION ( "MicroSMC driver for Linux" );
32
MODULE_AUTHOR      ( "XInstruments" );
33
MODULE_LICENSE     ( "GPL"  );
34
MODULE_VERSION     ( "1.0" );
35
 
36
 
37
static int num_devices = 0;     // Number of currently connected devices.
38
 
39
 
40
/*-----------------------------------------------------
41
                Init/Deinit section
42
-----------------------------------------------------*/
43
static int usmcdrv_init_module ( void )
44
{
45
        int res;
46
 
47
        printk ( KERN_DEBUG "Module usmcdrv init\n" );
48
        res = usb_register ( &usmc_driver );
49
 
50
        if ( res )
51
                err ( "usb_register failed. Error number %d", res );
52
 
53
        return  res;
54
}
55
 
56
 
57
static void usmcdrv_exit_module ( void )
58
{
59
        printk ( KERN_DEBUG "Module usmcdrv exit\n" );
60
 
61
        usb_deregister ( &usmc_driver );
62
}
63
 
64
 
65
module_init ( usmcdrv_init_module );
66
module_exit ( usmcdrv_exit_module );
67
 
68
 
69
/*-----------------------------------------------------
70
                Connect/Disconnect section
71
-----------------------------------------------------*/
72
static int usmc_probe ( struct usb_interface * interface,
73
                        const struct usb_device_id * id )
74
{
75
        struct usb_usmc * dev = NULL;
76
        int retval = -ENOMEM;
77
 
78
        dev = kzalloc ( sizeof ( *dev ), GFP_KERNEL );
79
 
80
        if ( dev == NULL ) {
81
                err ( "Out of memory" );
82
                goto    error;
83
        }
84
 
85
        kref_init ( &dev -> kref );
86
        sema_init ( &dev -> limit_sem, WRITES_IN_FLIGHT );
87
 
88
        dev -> udev = usb_get_dev ( interface_to_usbdev ( interface ) );
89
        dev -> interface = interface;
90
 
91
        usb_set_intfdata ( interface, dev );
92
        retval = usb_register_dev ( interface, &usmc_class );
93
 
94
        if ( retval )
95
        {
96
                err ( "Not able to get a minor for this device." );
97
                usb_set_intfdata ( interface, NULL );
98
                goto    error;
99
        }
100
 
101
        info ( USMC_DEV_NAME " device now attached to USBusmc-%d", interface -> minor );
102
        num_devices++;
103
 
104
        return  0;
105
error:
106
        if ( dev )
107
                kref_put ( &dev -> kref, usmc_delete );
108
 
109
        return  retval;
110
}
111
 
112
 
113
static void usmc_disconnect ( struct usb_interface * interface )
114
{
115
        struct usb_usmc * dev;
116
        int minor = interface -> minor;
117
 
118
#if HAVE_UNLOCKED_IOCTL
119
    struct mutex  fs_mutex;
120
   mutex_init(&fs_mutex);
121
   mutex_lock(&fs_mutex);
122
#else
123
   lock_kernel();
124
#endif
125
 
126
        dev = usb_get_intfdata ( interface );
127
        usb_set_intfdata ( interface, NULL );
128
 
129
        /* give back our minor */
130
        usb_deregister_dev ( interface, &usmc_class );
131
        num_devices--;
132
 
133
#if HAVE_UNLOCKED_IOCTL
134
   mutex_unlock(&fs_mutex);
135
#else
136
   unlock_kernel();
137
#endif
138
 
139
        /* decrement our usage count */
140
        kref_put ( &dev -> kref, usmc_delete );
141
 
142
        info ( USMC_DEV_NAME " #%d now disconnected", minor );
143
}
144
 
145
 
146
/*-----------------------------------------------------
147
                File operations section
148
-----------------------------------------------------*/
149
static int usmc_open ( struct inode * inode, struct file * file )
150
{
151
        struct usb_usmc      * dev;
152
        struct usb_interface * interface;
153
        int subminor;
154
        int retval = 0;
155
 
156
        info ( "usmc_open" );
157
 
158
        subminor = iminor ( inode );
159
 
160
        interface = usb_find_interface ( &usmc_driver, subminor );
161
 
162
        if ( !interface )
163
        {
164
                err ( "%s - error, can't find device for minor %d",
165
                     __FUNCTION__, subminor );
166
                retval = -ENODEV;
167
 
168
                goto    exit;
169
        }
170
 
171
        dev = usb_get_intfdata ( interface );
172
 
173
        if ( !dev )
174
        {
175
                retval = -ENODEV;
176
                goto    exit;
177
        }
178
 
179
        /* increment our usage count for the device */
180
        kref_get ( &dev -> kref );
181
 
182
        /* save our object in the file's private structure */
183
        file -> private_data = dev;
184
exit:
185
        return  retval;
186
}
187
 
188
 
189
static int usmc_release ( struct inode * inode, struct file * file )
190
{
191
        struct usb_usmc * dev;
192
 
193
        info ( "usmc_release" );
194
 
195
        dev = ( struct usb_usmc * ) file -> private_data;
196
 
197
        if ( dev == NULL )
198
                return  -ENODEV;
199
 
200
        /* decrement the count on our device */
201
        kref_put ( &dev -> kref, usmc_delete );
202
 
203
        return  0;
204
}
205
 
206
 
207
static long usmc_ioctl ( struct file * file, unsigned int ioctl_num, unsigned long ioctl_param )
208
{
209
        struct usb_usmc * dev;
210
        char * user_buf;
211
        char * kern_buf;
212
        char * kern_data_buf;
213
        __u32  dwTimeOut;
214
        long    dwRes;
215
        int    i;
216
        unsigned int pipe0;
217
 
218
        __u8  bRequestType;
219
        __u8  bRequest;
220
        __u16 wValue;
221
        __u16 wIndex;
222
        __u16 wLength;
223
 
224
        dev         = ( struct usb_usmc * ) file -> private_data;
225
        user_buf = ( char * ) ioctl_param;
226
        kern_buf = NULL;
227
        dwTimeOut   = 30000;
228
        dwRes       = USMC_SUCCESS;
229
 
230
        switch ( ioctl_num )
231
        {
232
        case IOCTL_GET_DESCRIPTOR_CONFIGURATION:
233
                info ( "usmc_ioctl. ioctl_num: IOCTL_GET_DESCRIPTOR_CONFIGURATION" );
234
 
235
                bsp_GetDescriptor ( GET_DESCRIPTOR_CONFIGURATION,
236
                                    &bRequestType,
237
                                    &bRequest,
238
                                    &wValue,
239
                                    &wIndex,
240
                                    &wLength );
241
 
242
                break;
243
        case IOCTL_GET_DESCRIPTOR_DEVICE:
244
                info ( "usmc_ioctl. ioctl_num: IOCTL_GET_DESCRIPTOR_DEVICE" );
245
 
246
                bsp_GetDescriptor ( IOCTL_GET_DESCRIPTOR_DEVICE,
247
                                    &bRequestType,
248
                                    &bRequest,
249
                                    &wValue,
250
                                    &wIndex,
251
                                    &wLength );
252
 
253
                break;
254
        case IOCTL_GET_DESCRIPTOR_STRING:
255
                info ( "usmc_ioctl. ioctl_num: IOCTL_GET_DESCRIPTOR_STRING" );
256
 
257
                bsp_GetDescriptor ( IOCTL_GET_DESCRIPTOR_STRING,
258
                                    &bRequestType,
259
                                    &bRequest,
260
                                    &wValue,
261
                                    &wIndex,
262
                                    &wLength );
263
 
264
                break;
265
        case IOCTL_GET_STATUS_DEVICE:
266
                info ( "usmc_ioctl. ioctl_num: IOCTL_GET_STATUS_DEVICE" );
267
 
268
                bsp_GetStatus ( IOCTL_GET_STATUS_DEVICE,
269
                                &bRequestType,
270
                                &bRequest,
271
                                &wValue,
272
                                &wIndex,
273
                                &wLength );
274
 
275
                break;
276
        case IOCTL_GET_STATUS_ENDPOINT:
277
                info ( "usmc_ioctl. ioctl_num: IOCTL_GET_STATUS_ENDPOINT" );
278
 
279
                bsp_GetStatus ( IOCTL_GET_STATUS_ENDPOINT,
280
                                &bRequestType,
281
                                &bRequest,
282
                                &wValue,
283
                                &wIndex,
284
                                &wLength );
285
 
286
                break;
287
        case IOCTL_GET_STATUS_INTERFACE:
288
                info ( "usmc_ioctl. ioctl_num: IOCTL_GET_STATUS_INTERFACE" );
289
 
290
                bsp_GetStatus ( IOCTL_GET_STATUS_INTERFACE,
291
                                &bRequestType,
292
                                &bRequest,
293
                                &wValue,
294
                                &wIndex,
295
                                &wLength );
296
 
297
                break;
298
        case IOCTL_GET_VERSION:
299
                info ( "usmc_ioctl. ioctl_num: IOCTL_GET_VERSION" );
300
 
301
                bsp_GetVersion ( &bRequestType,
302
                                 &bRequest,
303
                                 &wValue,
304
                                 &wIndex,
305
                                 &wLength );
306
 
307
                break;
308
        case IOCTL_GET_SERIAL:
309
                info ( "usmc_ioctl. ioctl_num: IOCTL_GET_SERIAL" );
310
 
311
                bsp_GetSerial ( &bRequestType,
312
                                &bRequest,
313
                                &wValue,
314
                                &wIndex,
315
                                &wLength );
316
 
317
                break;
318
        case IOCTL_GET_ENCODER_STATE:
319
                info ( "usmc_ioctl. ioctl_num: IOCTL_GET_ENCODER_STATE" );
320
 
321
                bsp_GetEncoderState ( &bRequestType,
322
                                      &bRequest,
323
                                      &wValue,
324
                                      &wIndex,
325
                                      &wLength );
326
 
327
                break;
328
        case IOCTL_GET_STATE:
329
                info ( "usmc_ioctl. ioctl_num: IOCTL_GET_STATE" );
330
 
331
                bsp_GetState ( &bRequestType,
332
                               &bRequest,
333
                               &wValue,
334
                               &wIndex,
335
                               &wLength );
336
 
337
                break;
338
        case IOCTL_GO_TO:
339
                info ( "usmc_ioctl. ioctl_num: IOCTL_GO_TO" );
340
 
341
                kern_buf = bsp_GoTo ( user_buf,
342
                           &bRequestType,
343
                           &bRequest,
344
                           &wValue,
345
                           &wIndex,
346
                           &wLength );
347
 
348
                break;
349
        case IOCTL_SET_MODE:
350
                info ( "usmc_ioctl. ioctl_num: IOCTL_SET_MODE" );
351
 
352
                kern_buf = bsp_SetMode ( user_buf,
353
                           &bRequestType,
354
                           &bRequest,
355
                           &wValue,
356
                           &wIndex,
357
                           &wLength );
358
 
359
                break;
360
        case IOCTL_SET_PARAMETERS:
361
                info ( "usmc_ioctl. ioctl_num: IOCTL_SET_PARAMETERS" );
362
 
363
                kern_buf = bsp_SetParameters ( user_buf,
364
                           &bRequestType,
365
                           &bRequest,
366
                           &wValue,
367
                           &wIndex,
368
                           &wLength );
369
 
370
                break;
371
        case IOCTL_DOWNLOAD:
372
                info ( "usmc_ioctl. ioctl_num: IOCTL_DOWNLOAD" );
373
 
374
                kern_buf = bsp_Download ( user_buf,
375
                           &bRequestType,
376
                           &bRequest,
377
                           &wValue,
378
                           &wIndex,
379
                           &wLength );
380
 
381
                break;
382
        case IOCTL_SET_SERIAL:
383
                info ( "usmc_ioctl. ioctl_num: IOCTL_SET_SERIAL" );
384
 
385
                kern_buf = bsp_SetSerial ( user_buf,
386
                           &bRequestType,
387
                           &bRequest,
388
                           &wValue,
389
                           &wIndex,
390
                           &wLength );
391
 
392
                break;
393
        case IOCTL_SET_CURRENT_POSITION:
394
                info ( "usmc_ioctl. ioctl_num: IOCTL_SET_CURRENT_POSITION" );
395
 
396
                bsp_SetCurrentPosition ( user_buf,
397
                           &bRequestType,
398
                           &bRequest,
399
                           &wValue,
400
                           &wIndex,
401
                           &wLength );
402
 
403
                break;
404
        case IOCTL_STOP_STEP_MOTOR:
405
                info ( "usmc_ioctl. ioctl_num: IOCTL_STOP_STEP_MOTOR" );
406
 
407
                bsp_StopStepMotor ( &bRequestType,
408
                           &bRequest,
409
                           &wValue,
410
                           &wIndex,
411
                           &wLength );
412
 
413
                break;
414
        case IOCTL_EMULATE_BUTTONS:
415
                info ( "usmc_ioctl. ioctl_num: IOCTL_EMULATE_BUTTONS" );
416
 
417
                bsp_EmulateButtons (  user_buf,
418
                           &bRequestType,
419
                           &bRequest,
420
                           &wValue,
421
                           &wIndex,
422
                           &wLength );
423
 
424
                break;
425
        case IOCTL_SAVE_PARAMETERS:
426
                info ( "usmc_ioctl. ioctl_num: IOCTL_SAVE_PARAMETERS" );
427
 
428
                bsp_SaveParameters ( &bRequestType,
429
                           &bRequest,
430
                           &wValue,
431
                           &wIndex,
432
                           &wLength );
433
 
434
                break;
435
        case IOCTL_GET_NOD:
436
                info ( "usmc_ioctl. ioctl_num: IOCTL_GET_NOD" );
437
                dwRes = 1;
438
                kern_buf = user_to_kernel ( user_buf, 1 );
439
                kern_buf [0] = num_devices;
440
 
441
                break;
442
        default:
443
                err ( "usmc_ioctl. unknown ioctl_num: %d", ioctl_num );
444
                dwRes = -1;
445
 
446
                break;
447
        }
448
 
449
 
450
        if ( dwRes == USMC_SUCCESS )
451
        {
452
                if ( ( bRequestType & USB_DIR_IN ) != USB_DIR_IN )
453
                {
454
                        kern_data_buf = wLength > 0 ? kern_buf + 4 : NULL;
455
                        pipe0 = usb_sndctrlpipe ( dev -> udev, 0 );
456
 
457
                } else {
458
                        kern_buf = ( char * ) kzalloc ( ( ssize_t ) wLength, GFP_KERNEL );
459
                        kern_data_buf = kern_buf;
460
                        pipe0 = usb_rcvctrlpipe ( dev -> udev, 0 );
461
                }
462
 
463
                dwRes = usb_control_msg ( dev -> udev,
464
                                          pipe0,
465
                                          bRequest,
466
                                          bRequestType,
467
                                          wValue,
468
                                          wIndex,
469
                                          kern_data_buf,
470
                                          wLength,
471
                                          dwTimeOut );
472
 
473
                if ( ( bRequestType & USB_DIR_IN ) == USB_DIR_IN )
474
                {
475
                        for ( i = 0 ; i < wLength ; i++ )
476
                                put_user ( kern_data_buf [i], user_buf + i );
477
                }
478
        } else if ( dwRes > 0 ) {
479
                for ( i = 0 ; i < dwRes ; i++ )
480
                        put_user ( kern_buf [i], user_buf + i );
481
        }
482
 
483
 
484
        kfree ( kern_buf );
485
 
486
        if ( dwRes < 0 ) {
487
                err ( "usmc_ioctl failed: dwRes: %d", (int) dwRes );
488
        } else {
489
                info ( "transmitted %d bytes over control pipe0", (int) dwRes );
490
        }
491
 
492
 
493
        return  dwRes;
494
}
495
 
496
 
497
/*-----------------------------------------------------
498
                Util functions section
499
-----------------------------------------------------*/
500
static void usmc_delete ( struct kref * kref )
501
{      
502
        struct usb_usmc * dev = to_usmc_dev ( kref );
503
 
504
        usb_put_dev ( dev -> udev );
505
        kfree ( dev );
506
}