struct urb<`a::A>
{ 
  spinlock_t lock;		// lock for the URB
  void *hcpriv;			// private data for host controller
  struct list_head urb_list;	// list pointer to all active urbs 
  struct urb<`a> *next;		// pointer to next URB	
  struct usb_device *dev;		// pointer to associated USB device
  unsigned int pipe;		// pipe information
  int status;			// returned status
  unsigned int transfer_flags;	// USB_DISABLE_SPD | USB_ISO_ASAP | etc.
  unsigned char *@nozeroterm `RC transfer_buffer;		// associated data buffer
  dma_addr_t transfer_dma;	// dma addr for transfer_buffer
  int transfer_buffer_length;	// data buffer length
  int actual_length;              // actual data buffer length	
  int bandwidth;			// bandwidth for this transfer request (INT or ISO)
  unsigned char *setup_packet;	// setup packet (control only)
  dma_addr_t setup_dma;		// dma addr for setup_packet
  //
  int start_frame;		// start frame (iso/irq only)
  int number_of_packets;		// number of packets in this request (iso)
  int interval;                   // polling interval (irq only)
  int error_count;		// number of errors in this transfer (iso only)
  int timeout;			// timeout (in jiffies)
  //
  `a *context;			// context for completion routine
  void (*complete)(struct urb<`a> *);
  //  usb_complete_t complete;	// pointer to completion routine
  //
  struct iso_packet_descriptor iso_frame_desc[0];//cheap trick
};

//version with existential ... 
// struct urb<`a::A>
// { <`i::I>
//   spinlock_t lock;		// lock for the URB
//   void *hcpriv;			// private data for host controller
//   struct list_head urb_list;	// list pointer to all active urbs 
//   struct urb<`a> *next;		// pointer to next URB	
//   struct usb_device *dev;		// pointer to associated USB device
//   unsigned int pipe;		// pipe information
//   int status;			// returned status
//   unsigned int transfer_flags;	// USB_DISABLE_SPD | USB_ISO_ASAP | etc.
//   unsigned char *{valueof(`i)} @nozeroterm  transfer_buffer;		// associated data buffer
//   dma_addr_t transfer_dma;	// dma addr for transfer_buffer
//   tag_t<`i> transfer_buffer_length;	// data buffer length
//   int actual_length;              // actual data buffer length	
//   int bandwidth;			// bandwidth for this transfer request (INT or ISO)
//   unsigned char *setup_packet;	// setup packet (control only)
//   dma_addr_t setup_dma;		// dma addr for setup_packet
//   //
//   int start_frame;		// start frame (iso/irq only)
//   int number_of_packets;		// number of packets in this request (iso)
//   int interval;                   // polling interval (irq only)
//   int error_count;		// number of errors in this transfer (iso only)
//   int timeout;			// timeout (in jiffies)
//   //
//   `a *context;			// context for completion routine
//   void (*complete)(struct urb<`a> *);
//   //  usb_complete_t complete;	// pointer to completion routine
//   //
//   struct iso_packet_descriptor iso_frame_desc[0];//cheap trick
// };


void usb_free_urb(struct urb<`a> *urb);
int usb_submit_urb(struct urb<`a> *urb);
int usb_unlink_urb(struct urb<`a> *urb);
// struct urb
// { 
//   spinlock_t lock;		// lock for the URB
//   void *hcpriv;			// private data for host controller
//   struct list_head urb_list;	// list pointer to all active urbs 
//   struct urb *next;		// pointer to next URB	
//   struct usb_device *dev;		// pointer to associated USB device
//   unsigned int pipe;		// pipe information
//   int status;			// returned status
//   unsigned int transfer_flags;	// USB_DISABLE_SPD | USB_ISO_ASAP | etc.
//   void *transfer_buffer;		// associated data buffer
//   dma_addr_t transfer_dma;	// dma addr for transfer_buffer
//   int transfer_buffer_length;	// data buffer length
//   int actual_length;              // actual data buffer length	
//   int bandwidth;			// bandwidth for this transfer request (INT or ISO)
//   unsigned char *setup_packet;	// setup packet (control only)
//   dma_addr_t setup_dma;		// dma addr for setup_packet
//   //
//   int start_frame;		// start frame (iso/irq only)
//   int number_of_packets;		// number of packets in this request (iso)
//   int interval;                   // polling interval (irq only)
//   int error_count;		// number of errors in this transfer (iso only)
//   int timeout;			// timeout (in jiffies)
//   //
//   void *context;			// context for completion routine
//   usb_complete_t complete;	// pointer to completion routine
//   //

//   struct iso_packet_descriptor iso_frame_desc[0]; //nasty trick
// };


struct usb_interface {
  <`i::I>
  struct usb_interface_descriptor *@numelts(valueof(`i)) altsetting;
  
  int act_altsetting;		/* active alternate setting */
  tag_t<`i> num_altsetting;		/* number of alternate settings */
  int max_altsetting;             /* total memory allocated */
  
  struct usb_driver *driver;	/* driver */
  void *private_data;
};

struct usb_driver {
  struct module *owner;

  const char *name;

  void *(*probe)(struct usb_device *dev,		/* the device */
		 unsigned intf,			/* what interface */
		 const struct usb_device_id *id	/* from id_table */
		 )__attribute__((no_throw));

  void (*disconnect)(struct usb_device *, void *)__attribute__((no_throw));

  struct list_head driver_list;

  struct file_operations *fops;
  int minor;

  struct semaphore serialize;

  int (*ioctl)(struct usb_device *dev, unsigned int code, void *buf);

  const struct usb_device_id *id_table;
};


extern int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request, __u8 requesttype, 
			   __u16 value, __u16 index, `a *`r::R data, __u16 size, int timeout);

int usb_string(struct usb_device *dev, int index, char *{valueof(`i)}@nozeroterm buf, tag_t<`i> size);
