I'm having a problem where the kernel is freezing when the function
sohci_unlink_urb is attempting to shedule_timeout(timeout). The exact point
in the kerneL where it freezes is in add_timer(&timer) after the spinlock is
locked.
I attempted to fix this problem by setting the USB_ASYNC_UNLINK flag when the
urbs are created in the probe function. This stops the freezing of the
kernel, but my computer starts making a continuous humming noise after the
calls to sohci_unlink_urb. I'm not sure why my computer is humming. It's
almost as if the usb driver were constantly working even after all the urbs
were unlinked.
The driver code is attached.
Any explanations for this strange behaviour?
--
Camotion
Software Development
/***************************************************************************
RasidDriver.c - description
-------------------
begin : Fri Jan 12 2001
copyright : (C) 2001 by CAMotion
email : [EMAIL PROTECTED]
***************************************************************************/
/* TODO
*
* on read, if count == 2*TRANSFER_PACKET_SIZE, then also send contents of last_sent buffer
*
*/
// Proprietary intellectual property, (c) 2000 CAMotion, Inc.
// Source and listing must be protected.
/* /////////////////////////////////////////////////////////////////////////////
Module Name: modRasidDriver.c
Date: January 2002
Description: RASID Linux device driver
Module Function:
Notes: By default, all functions will return a negative integer under
error conditions.
This program can be compiled to the module RasidDriver.o with
the following command:
gcc -I/usr/src/linux/include
-Wall -O2 -o modRasidDriver.o -c modRasidDriver.c
This module can then be inserted into the Kernel:
insmod modRasidDriver.o
Caution!!! This program compiles to a device driver (as a Kernel
loadable module). Therefore, this code is intended to run in Kernel
space as a priveleged process. It has the power to do anything
on the system including crashing the Kernel.
Owner: CAMotion, Inc.
Atlanta, GA 30318
404.874.0090
Copyright (c) 2002 CAMotion, Inc. All rights reserved.
06-13-02 Added call to devfs_register in probe to avoid use of "mknod" call
Added a member in the rasid context struct for the devfs handle
Rewritten: Andrew M. Henshaw 2/1/01
Original: Jerry Volcy
///////////////////////////////////////////////////////////////////////////// */
/* =======================================================================
This section contains include files and certain preprocessing options
required to program in Kernel space.
======================================================================= */
#ifndef __KERNEL__
# define __KERNEL__
#endif
#ifndef MODULE
# define MODULE
#endif
#define __NO_VERSION__ //no kernel version
#include <linux/module.h>
//#include <linux/modversions.h>
#if defined (CONFIG_SMP)
#define __SMP__
#endif
#if defined (CONFIG_MODVERSIONS)
//#define MODVERSIONS
//#include <linux/modversions.h>
#endif
//#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/usb.h>
//#include <linux/time.h>
#include <linux/errno.h> //definition of error symbols EPIPE, ENOENT, etc...
//also includes asm/errno.h
//#include <linux/sched.h>
//#include <linux/devfs_fs_kernel.h>
/* =======================================================================
Kernel version definition
=======================================================================*/
char kernel_version [] = UTS_RELEASE;
extern wait_queue_head_t log_wait;
/* =======================================================================
Selection of Major#
The following Major numbers are reserved for local (user defined) devices:
42, 120-127. No standard production device should use these numbers.
Usually, we are free to pick any one of these numbers for our driver.
But, since RASID is a USB device, by convention it should have major #180.
======================================================================= */
#define RASID_MAJOR 180
/* =======================================================================
Minor number for the RASID USB driver: This number must be a multiple
of 16. The specified minor number and the 15 following numbers are assigned
to the driver. This makes it possible to serve up to 16 similar USB devices
with a single driver. Here are the minor numbers currently assigned on
this computer (by inspection of /dev/usb):
BASE MNR# RANGE DEVICE
0 (0*16) 0-15 lp
32 (2*16) 32-47 mdc800
48 (3*16) 48-63 scanner
64 (4*16) 64-79 rio50
80 (5*16) 80-95 dc2xx
240(15*16) 240-255 dabusb
It's probably safe to assume that these are standard assignments.
Presumably, base minor# 16, 96-224 ((1, 6-14)*16 )are available.
Since the assignment seems to start from the lower numbers
to the higher, let's use a relatively large minor number to
avoid conflicts in the near future. Use #13*16=208 until wisdom
to the contrary is found.
======================================================================= */
#define RASID_BASE_MINOR 208 /* we can handle 16 RASIDs with minor
numbers that will range from 208 - 223)*/
/* =======================================================================
Selection of IOCTL base address.
It will also be necessary to pick a base number for ioctl calls made to the
driver. Standard ioctl base number assignments can be found in
/usr/src/linux/Documentation/ioctl-number.txt. Again we are free to pick any
base address that is not assigned. 0xbb is probably a good choice: it is far
away from anything else out there.
======================================================================= */
#define RASID_IOCTL_BASE 0xbb
/* =======================================================================
IOCTL calls
These are the IOCTL calls for the RASID driver.
======================================================================= */
#define RASID_READ_DATA _IO(RASID_BASE, 0);
#define RASID_SEND_COMMAND _IOWR(RASID_BASE, 1);
//etc...
/* ==================Init_H=====================================================
Maximum number of RASIDS
Currently, the Linux USB core driver allows each loaded driver to control
a maximum of 16 devices. This will limit the number of RASIDS attached to
any system to 16.
======================================================================= */
#define MAX_NUM_RASIDS 16
/* =======================================================================
Axes per RASID
The number of Axes each RASID can currently control
======================================================================= */
#define AXES_PER_RASID 1
/* =======================================================================
Maximum number of Axes
======================================================================= */
#define MAX_NUM_AXES MAX_NUM_RASIDS*AXES_PER_RASID
/* =======================================================================
USB transfer buffer length
======================================================================= */
#define NUMBER_OF_PACKETS 1
#define TRANSFER_PACKET_SIZE 64 //this is the max packet size
#define TRANSFER_BUFFER_LENGTH NUMBER_OF_PACKETS*TRANSFER_PACKET_SIZE
/* =======================================================================
RASID USB options
======================================================================= */
#define RCV_ENDPOINT 0x02 //receive endpoint
#define SND_ENDPOINT 0x82 //send endpoint
#define RCV_TIMEOUT 10000 //timeout in jiffies
#define SND_TIMEOUT 10000 //timeout in jiffies
#define ISOC_RCV_INTERVAL 1 //isochronous interval (milliseconds)
#define ISOC_SND_INTERVAL 1 //isochronous interval (millisecodns)
#define RASID_VENDOR_ID 0x0471 //Vendor ID#
#define RASID_PRODUCT_ID 0x0222 //Product ID#
#define RASID_IFNUM 0 //interface # this driver handles
#define RASID_CONF 1 //configuration # this driver handles
#define SND_URB_POOL_SIZE 2
#define RCV_URB_POOL_SIZE 2
#define URB_POOL_SIZE (SND_URB_POOL_SIZE + RCV_URB_POOL_SIZE)
#define IDLE_SIZE 1
#define MAX_BUFFER_INDEX 2
/* =======================================================================
DevFS file name length
Length of the string holding the filename of a rasid in /dev/
Enough to hold "Rasid" + RasidNum_ + \n
======================================================================= */
//#define FILE_NAME_LENGTH 8
/* =======================================================================
Debugging option
Define the symbol DEGUG to enable verbose status logging into /proc/kmsg
use the dmesg command to read the messages.
======================================================================= */
#define DEBUG
/* =======================================================================
This macro logs messages to /proc/kmsg if DEBUG is defined.
The macro "MSG(...)" is simply a shorthand for "printk(KERN_DEBUG ...)"
when the symbol DEBUG is defined. When DEBUG is not defined, the
macro evaluates to NULL (no action taken).
======================================================================= */
#ifdef DEBUG
#define MSG(string, args...) printk(KERN_INFO string, ##args)
#else
#define MSG(string, args...)
#endif //#ifdef DEBUG
/* =======================================================================
min macro
======================================================================= */
#define min(x, y) ((x <= y) ? x : y)
/* =======================================================================
table of devices that work with the RASID driver
======================================================================= */
static struct usb_device_id rasid_table[] =
{
{USB_DEVICE(RASID_VENDOR_ID, RASID_PRODUCT_ID)},
{}
};
MODULE_DEVICE_TABLE(usb, rasid_table);
/* =======================================================================
Forward declarations
======================================================================= */
struct rasid_dev_context;
static struct usb_driver RasidDriver;
void rasid_rcv_complete(struct urb *purb);
void rasid_snd_complete(struct urb *purb);
void show_urb(purb_t urb);
/* =======================================================================
Forward declarations for _fops
======================================================================= */
ssize_t rasid_read (struct file *file, char *buf, size_t count, loff_t *offset);
ssize_t rasid_write (struct file *file, const char *buf, size_t count, loff_t *offset);
int rasid_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg);
int rasid_open (struct inode *inode, struct file *file);
int rasid_release(struct inode *inode, struct file *file);
loff_t rasid_lseek (struct file *file, loff_t offset, int orig) ;
static struct file_operations rasid_fops;
/* =======================================================================
Global declarations
======================================================================= */
/*this is a global array of rasid device context pointers. The array is
static, its elements will therefore be initialized to NULL;*/
static struct rasid_dev_context *p_rasid_dev_context[MAX_NUM_RASIDS]={NULL, /*...*/};
static int nNumRasids = 0; //the number of attached RASID devices;
int write_try = 0;
int slept = 0;
int interrupted = 0;
/* =======================================================================
This is our new custom driver context structure. It will contain:
pointers to the send and receive URBs and misc. device specific members.
======================================================================= */
struct rasid_dev_context
{
struct usb_device *rasid_dev;
__u16 RasidNum; //RaisdNum stores the position of
//the pointer to the current device context
//in the global RASID device context pointer array.
//Example: there exists a global array of pointers
//to RASID type device context structures:
//p_rasid_dev_context. If p_rasid_dev_context[5]
//points to the current driver context, then
//RasidNum = 5;
//This is needed for deallocation purposes in disconnect_rasid();
purb_t urbs[URB_POOL_SIZE] ; //urbs for ping-ponging sends and receives
char latest_data[TRANSFER_PACKET_SIZE] ; //buffer for isochronously-read data
char latest_sent[TRANSFER_PACKET_SIZE];
spinlock_t read_lock;
int open_ctr;
char write_buffer[MAX_BUFFER_INDEX + 1][TRANSFER_PACKET_SIZE];
int write_buffer_length[MAX_BUFFER_INDEX + 1];
int put_index ;
int get_index ;
int accepted;
int idle_run;
int idle;
struct semaphore slots;
//devfs_handle_t devfs; //handle for node in dev file system
//char fileName[FILE_NAME_LENGTH]; //file name in dev
//struct wait_queue * wait;
/////
__u32 rcv_pipe; //receive pipe
__u32 snd_pipe; //send pipe
};
/* =======================================================================
int init_module(void)
Non-static declaration here. This function must be exported to Kernel
space.
======================================================================= */
int init_module(void)
{
__s16 res;
res = usb_register(&RasidDriver);
if (res)
{
MSG("RASID driver failed to register.\n");
return res;
}
MSG("RASID driver registered.\n");
return 0;
}
/* =======================================================================
void cleanup_module(void)
Non static declaration here. This function must be exported to Kernel
space.
======================================================================= */
void cleanup_module(void)
{
MSG("Closing RASID driver.\n");
usb_deregister(&RasidDriver);
}
static void unlink_open_urbs(struct rasid_dev_context *context)
{
purb_t purb ;
int i ;
int status ;
if (context)
{
for (i = 0; i < URB_POOL_SIZE; i++)
{
purb = context->urbs[i];
show_urb(purb);
if (purb->status)
{
status = usb_unlink_urb(purb);
}
}
}
}
/* =======================================================================
static void disconnect_rasid(struct usb_device*, void *)
In the function, we must de-allocate all resources previously allocated
in probe_rasid
======================================================================= */
static void disconnect_rasid(struct usb_device *dev, void *drv_context)
{
struct rasid_dev_context *context = (struct rasid_dev_context*)drv_context;
purb_t purb ;
int i;
if (context)
{
unlink_open_urbs(context);
//free the URB pool
for (i = 0; i < URB_POOL_SIZE; i++)
{
purb = context->urbs[i];
kfree(purb->transfer_buffer) ;
usb_free_urb(purb);
}
//free the appropriate slot in the global context pointer array
//NULL implies the slot is available
if (p_rasid_dev_context[context->RasidNum])
p_rasid_dev_context[context->RasidNum] = NULL;
//unregister with devFS
//devfs_unregister(context->devfs);
MSG("Disconnecting device with Major# %d and Minor# %d...\n", RASID_MAJOR, context->RasidNum + RASID_BASE_MINOR);
//de-allocate space for the device context
kfree(context);
nNumRasids--;
MSG("Number of RASIDs in system: %d\n", nNumRasids);
}
return;
}
/* =======================================================================
ssize_t rasid_read(struct file *file, char *buf, size_t count, loff_t *offset)
All inputs from RASID to the driver is through endpoint #82 which is
setup for 64-byte isochronous transfers (IN)
======================================================================= */
ssize_t rasid_read(struct file *file, char *buf, size_t count, loff_t *offset)
{
struct rasid_dev_context *context = (struct rasid_dev_context *)file->private_data;
unsigned long irqflags;
//DANGER - should not use spinlocks copying to user space
spin_lock_irqsave(&(context->read_lock), irqflags);
count = min(count, TRANSFER_PACKET_SIZE);
//DANGER - memcopy assumes program code is not paged out aka enough memory
memcpy(buf, context->latest_data, count);
spin_unlock_irqrestore(&(context->read_lock), irqflags);
return count;
return 0 ;
}
/* =======================================================================
RASID URB transfer callback routine
======================================================================= */
void rasid_rcv_complete(purb_t purb)
{
struct rasid_dev_context *context = (struct rasid_dev_context*)(purb->context);
// MSG("recieved a message at %ul .\n", jiffies);
memcpy(context->latest_data, purb->transfer_buffer, TRANSFER_PACKET_SIZE);
}
/* =======================================================================
ssize_t rasid_write(struct file *file, const char *buf, size_t count, loff_t *offset)
All outputs from the driver to RASID is through endpoint #02 which is
setup for 64-byte isochronous transfers (OUT)
======================================================================= */
ssize_t rasid_write(struct file *file, const char *buf, size_t count, loff_t *offset)
{
struct rasid_dev_context *context = (struct rasid_dev_context*) file->private_data ;
int writecount = 0 ;
int next_index ;
int sem_return ;
write_try++;
/* if( sem_return = down_trylock(&context->slots))
{
slept++;
sem_return = down_interruptible(&context->slots) ;
}
*/
sem_return = down_interruptible(&context->slots) ;
if (sem_return < 0)
{
interrupted ++;
return sem_return; // Interrupted by a signal
}
next_index = (context->put_index + 1) % MAX_BUFFER_INDEX ;
if ( next_index != context->get_index)
{
writecount = min(count, TRANSFER_PACKET_SIZE) ;
memcpy(context->write_buffer[context->put_index], buf, writecount);
context->write_buffer_length[context->put_index] = writecount;
context->put_index = next_index ;
}
else
MSG("Inconceivable! Reached end of buffer\n");
return writecount;
}
/* =======================================================================
RASID URB transfer callback routine
======================================================================= */
void rasid_snd_complete(struct urb *purb)
{
unsigned long irqflags;
struct rasid_dev_context *context = (struct rasid_dev_context*)(purb->context);
struct timeval tv; //ANTON CHANGE
// save the last non-idle message sent (for monitoring purposes)
if (*(char *)purb->transfer_buffer != (char)0xff)
{
spin_lock_irqsave(&(context->read_lock), irqflags);
memcpy(context->latest_sent,
purb->transfer_buffer,
TRANSFER_PACKET_SIZE);
spin_unlock_irqrestore(&(context->read_lock), irqflags);
}
if (context->get_index != context->put_index)
{
// move the data from the queue into the packet
memcpy(purb->transfer_buffer,
context->write_buffer[context->get_index],
context->write_buffer_length[context->get_index]);
context->accepted++;
context->get_index = (context->get_index + 1) % MAX_BUFFER_INDEX ;
do_gettimeofday(&tv);
printk(KERN_DEBUG "INT %d\n", tv.tv_usec); //ANTON CHANGE
up(&context->slots);
}
else
{
context->idle++;
*(char *)purb->transfer_buffer = (char)0xff;
}
// display some statistics every 1000 packets
if ((context->idle + context->accepted) == 100)
{
if(context->idle)
{
/*MSG ("Idle %d packets out of 100 (After run of %d)\n",
context->idle, context->idle_run);
MSG("Wrote %d times\nSlept %d times\nInterrupted %d times\n\n",
write_try, slept, interrupted);*/
context->idle_run = 0;
}
else
{
context->idle_run++;
}
context->idle = 0;
context->accepted = 0;
}
return;
}
/* =======================================================================
int rasid_open(struct inode *inode, struct file *file)
======================================================================= */
int rasid_open(struct inode *inode, struct file *file)
{
int i;
int ret_code ;
int rcv_start ;
unsigned long irqflags;
int rasidNum = MINOR(inode->i_rdev) - RASID_BASE_MINOR;
struct rasid_dev_context *context = p_rasid_dev_context[rasidNum] ;
MSG("Opening rasid num: %d\n", rasidNum);
file->private_data = (void *) context;
spin_lock_irqsave(&(context->read_lock), irqflags);
if (!context->open_ctr)
{
// this is the only(first) app to open this device
///// set the free buffer to the first one
context->put_index = 0 ;
context->get_index = 0 ;
// init statistics
context->accepted = 0;
context->idle = 0;
context->idle_run = 0;
//context->wait = NULL ;
sema_init(&context->slots, MAX_BUFFER_INDEX - 1);
// set up the ping-pong urbs for empty sends
for (i = 0; i < SND_URB_POOL_SIZE; i++)
{
context->urbs[i]->iso_frame_desc[0].length = TRANSFER_PACKET_SIZE;
context->urbs[i]->transfer_buffer_length = TRANSFER_PACKET_SIZE;
*(char *)context->urbs[i]->transfer_buffer = (char) 0xff; // idle packet
context->urbs[i]->next = context->urbs[(i+1) % SND_URB_POOL_SIZE] ;
}
// set up the ping-pong urbs for isochronous receives
rcv_start = SND_URB_POOL_SIZE ;
for (i = 0; i < RCV_URB_POOL_SIZE; i++)
{
context->urbs[i+rcv_start]->iso_frame_desc[0].length = TRANSFER_PACKET_SIZE;
context->urbs[i+rcv_start]->transfer_buffer_length = TRANSFER_PACKET_SIZE;
context->urbs[i+rcv_start]->next =
context->urbs[((i+1) % RCV_URB_POOL_SIZE) + rcv_start] ;
}
for (i = 0; i < URB_POOL_SIZE; i++)
{
context->urbs[i]->dev = context->rasid_dev;
ret_code = usb_submit_urb(context->urbs[i]);
show_urb(context->urbs[i]);
if (ret_code)
{
MSG("Rasid open: urb submit failed: %d\n", ret_code);
return ret_code;
}
//MSG("usb_submit_urb\n");
}
}
context->open_ctr++;
spin_unlock_irqrestore(&(context->read_lock), irqflags);
MOD_INC_USE_COUNT;
return 0;
}
/* =======================================================================
======================================================================= */
int rasid_release(struct inode *inode, struct file *file)
{
int RasidNum ;
unsigned long irqflags;
struct rasid_dev_context *context ;
RasidNum = MINOR(inode->i_rdev) - RASID_BASE_MINOR;
MSG("Releasing rasid num: %d\n", RasidNum);
context = p_rasid_dev_context[RasidNum] ;
//MSG("Idle run: %d\n", context->idle_run);
MSG("RASID closing\n");
spin_lock_irqsave(&(context->read_lock), irqflags);
context->open_ctr--;
if (!context->open_ctr)
{
unlink_open_urbs(context) ;
}
spin_unlock_irqrestore(&(context->read_lock), irqflags);
MOD_DEC_USE_COUNT;
return 0;
}
/* =======================================================================
int rasid_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
======================================================================= */
int rasid_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
return 0;
}
/* =======================================================================
loff_t rasid_lseek(struct inode *inode, struct file *file, off_t offset, int orig) ;
======================================================================= */
loff_t rasid_lseek(struct file *file, loff_t offset, int orig)
{
return 0;
}
/* =======================================================================
======================================================================= */
static void *probe_rasid(struct usb_device *dev,
unsigned int ifnum,
const struct usb_device_id *id_table)
{
int i, j;
struct rasid_dev_context *context ;
purb_t purb ;
//devfs_handle_t oldNode = NULL;
//__s16 x;
__u16 RasidNum_; //If the probing device is a RASID, RasidNum_
//will be its position in the global driver
//context array. This is needed for
//de-allocation in disconnect_rasid();
//besides the Vendor ID and the Product ID, we should check the
//interface number
if (dev->descriptor.idVendor == RASID_VENDOR_ID &&
dev->descriptor.idProduct == RASID_PRODUCT_ID)
{
//may want to check the configuration # also
MSG("A CAMotion RASID device has been connected!\n");
if( ifnum != RASID_IFNUM) goto p0; //no match
}
else goto p0; //no match
if (nNumRasids == MAX_NUM_RASIDS)
{
MSG("All minor numbers are assigned.\n");
goto p0; //no more minor devices remaining
}
//find the next available minor number
for (RasidNum_ = 0; RasidNum_ < MAX_NUM_RASIDS; RasidNum_++)
{
if (!p_rasid_dev_context[RasidNum_]) break; //found an un-allocated driver context
}
//allocate space for the device context
if (!(p_rasid_dev_context[RasidNum_] = kmalloc(sizeof(struct rasid_dev_context), GFP_KERNEL)) )
{
MSG("Out of memory while allocating space for the device context.\n");
goto p0;
}
context = p_rasid_dev_context[RasidNum_] ;
memset(context, 0, sizeof(struct rasid_dev_context));
context->RasidNum = RasidNum_; //store the position w/in the global table permanently
context->rasid_dev = dev; //store the usb part of the driver context
spin_lock_init(&(context->read_lock));
usb_set_configuration(context->rasid_dev, RASID_CONF);
usb_set_interface (context->rasid_dev, RASID_IFNUM, 0);
//
//next, create the input and output pipes
//
context->rcv_pipe = usb_rcvisocpipe(context->rasid_dev, RCV_ENDPOINT );
context->snd_pipe = usb_sndisocpipe(context->rasid_dev, SND_ENDPOINT );
//
// Create a pool of URBs for later usage
//
for (i = 0; i < URB_POOL_SIZE; i++)
{
//first, allocate the URBs
if( (purb = (purb_t)usb_alloc_urb(NUMBER_OF_PACKETS)) == NULL )
{
MSG("Error allocating URB.\n");
goto p1; //de-allocate buffer
}
context->urbs[i] = purb ;
memset(purb, 0, sizeof(urb_t));
//
//fill in the URB
//
purb->dev = context->rasid_dev;
purb->transfer_flags = USB_ISO_ASAP | USB_ASYNC_UNLINK;
purb->number_of_packets = NUMBER_OF_PACKETS; //iso only
purb->context = context; //pointer to the URB's parent device context
purb->transfer_buffer_length = TRANSFER_BUFFER_LENGTH;
if (i < SND_URB_POOL_SIZE) //setup a send URB
{
purb->pipe = context->snd_pipe;
purb->interval = ISOC_SND_INTERVAL;
purb->timeout = SND_TIMEOUT;
purb->complete = rasid_snd_complete;
}
else //setup a receive URB
{
purb->pipe = context->rcv_pipe;
purb->interval = ISOC_RCV_INTERVAL;
purb->timeout = RCV_TIMEOUT;
purb->complete = rasid_rcv_complete;
}
for (j = 0; j < NUMBER_OF_PACKETS; j++)
{
purb->iso_frame_desc[j].offset = (TRANSFER_PACKET_SIZE) * j ;
purb->iso_frame_desc[j].length = TRANSFER_PACKET_SIZE ;
}
if(!(purb->transfer_buffer = (char*)kmalloc(TRANSFER_BUFFER_LENGTH, GFP_KERNEL)) )
{
MSG("Out of memory while allocating I/O buffer.\n");
goto p1; //de-allocate entire driver context
}
}
//
//all is well, increment the number of RASIDS attached by one
//
nNumRasids++;
MSG("Number of RASIDs in system: %d\n", nNumRasids);
MSG("Current device has major# %u and Minor# %u.\n", RASID_MAJOR, RasidNum_ + RASID_BASE_MINOR);
//
// make the file in the dev filesystem
//
/*===========================Unused DevFS Code==================================
sprintf(context->fileName, "rasid%d", RasidNum_);
oldNode = (devfs_handle_t) get_root_entry();
if(oldNode)
{
MSG("found root entry\n");
}
oldNode = devfs_find_handle (NULL,
"rasid1",
(unsigned int) NULL,
(unsigned int) NULL,
DEVFS_SPECIAL_CHR,
1);
if( oldNode )
{
MSG("Removing old node from /dev/%s", context->fileName);
devfs_unregister(oldNode);
}
context->devfs = devfs_register (NULL,
context->fileName,
DEVFS_FL_DEFAULT,
RASID_MAJOR,
RasidNum_ + RASID_BASE_MINOR,
S_IFCHR | S_IRUSR | S_IWUSR |
S_IRGRP | S_IWGRP | S_IROTH,
&rasid_fops,
NULL);
if( !context->devfs )
{
MSG("Unable to create rasid file in /dev/.\n");
MSG("name: %s %d\n", context->fileName, context->devfs);
}
==========================================================================*/
return context; //return the driver context structure
p1: kfree(context); //Free Device context
MSG("Device context freed.\n");
p0: return NULL; //Call failed
}
/* =======================================================================
static struct file_operations rasid_fops
======================================================================= */
static struct file_operations rasid_fops=
{
owner: THIS_MODULE,
llseek: rasid_lseek,
read: rasid_read,
write: rasid_write,
ioctl: rasid_ioctl,
open: rasid_open,
release: rasid_release
};
void show_urb(purb_t purb)
{
return; // Short circuit
MSG("Status : %10d Actual length: %8d\n", purb->status, purb->actual_length);
MSG("Address : %10p Next: %p\n", purb, purb->next);
MSG("Start frame : %10d Error count: %8d Frame length: %d\n",
purb->start_frame, purb->error_count, purb->iso_frame_desc[0].length);
MSG("Dev : %10p\n\n", purb->dev);
}
/* =======================================================================
static struct usb_driver RasidDriver
======================================================================= */
static struct usb_driver RasidDriver=
{
name: "rasid",
probe: probe_rasid,
disconnect: disconnect_rasid,
fops: &rasid_fops,
minor: RASID_BASE_MINOR,
id_table: rasid_table,
};
/* =======================================================================
Signal Values.
The values of a few signals are listed here only as an aid in debugging.
These can be found in usr/include/asm/errno.h and usr/include/linux/errno.h.
ENOMEM = 12
ENXIO = 6
EINVAL = 22 //Log off and go home
EAGAIN = 11
EFBIG = 27
EPIPE = 32
EMSGSIZE = 90
ENOENT = 2
EILSEQ = 84 //illegal byte sequence
ETIMEDOUT = 110 //connection timed out
======================================================================= */