usb-char.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:19k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * (C) Copyright 2000-2001 Extenex Corporation
  3.  *
  4.  * This program is free software; you can redistribute it and/or modify
  5.  * it under the terms of the GNU General Public License as published by
  6.  * the Free Software Foundation; either version 2 of the License, or
  7.  * (at your option) any later version.
  8.  *
  9.  * This program is distributed in the hope that it will be useful,
  10.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  * GNU General Public License for more details.
  13.  *
  14.  * You should have received a copy of the GNU General Public License
  15.  * along with this program; if not, write to the Free Software
  16.  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17.  *
  18.  *  usb-char.c
  19.  *
  20.  *  Miscellaneous character device interface for SA1100 USB function
  21.  * driver.
  22.  *
  23.  *  Background:
  24.  *  The SA1100 function driver ported from the Compaq Itsy project
  25.  *  has an interface, usb-eth.c, to feed network packets over the
  26.  *  usb wire and into the Linux TCP/IP stack.
  27.  *
  28.  *  This file replaces that one with a simple character device
  29.  *  interface that allows unstructured "byte pipe" style reads and
  30.  *  writes over the USB bulk endpoints by userspace programs.
  31.  *
  32.  *  A new define, CONFIG_SA1100_USB_NETLINK, has been created that,
  33.  *  when set, (the default) causes the ethernet interface to be used.
  34.  *  When not set, this more pedestrian character interface is linked
  35.  *  in instead.
  36.  *
  37.  *  Please see linux/Documentation/arm/SA1100/SA1100_USB for details.
  38.  *
  39.  *  ward.willats@extenex.com
  40.  *
  41.  *  To do:
  42.  *  - Can't dma into ring buffer directly with pci_map/unmap usb_recv
  43.  *    uses and get bytes out at the same time DMA is going on. Investigate:
  44.  *    a) changing usb_recv to use alloc_consistent() at client request; or
  45.  *    b) non-ring-buffer based data structures. In the meantime, I am using
  46.  *    a bounce buffer. Simple, but wasteful.
  47.  */
  48. #include <linux/module.h>
  49. #include <linux/config.h>
  50. #include <linux/miscdevice.h>
  51. #include <linux/slab.h>
  52. #include <linux/init.h>
  53. #include <linux/cache.h>
  54. #include <linux/poll.h>
  55. #include <linux/circ_buf.h>
  56. #include <linux/timer.h>
  57. #include <asm/io.h>
  58. #include <asm/semaphore.h>
  59. #include <asm/proc/page.h>
  60. #include <asm/mach-types.h>
  61. #include "usb-char.h"
  62. #include "pxa_usb.h"
  63. //////////////////////////////////////////////////////////////////////////////
  64. // Driver  Options
  65. //////////////////////////////////////////////////////////////////////////////
  66. #define VERSION  "0.4"
  67. #define VERBOSITY 1
  68. #if VERBOSITY
  69. # define PRINTK(x, a...) printk (x, ## a)
  70. #else
  71. # define PRINTK(x, a...) /**/
  72. #endif
  73. //////////////////////////////////////////////////////////////////////////////
  74. // Globals - Macros - Enums - Structures
  75. //////////////////////////////////////////////////////////////////////////////
  76. #ifndef MIN
  77. #define MIN( a, b ) ((a)<(b)?(a):(b))
  78. #endif
  79. typedef int bool; enum { false = 0, true = 1 };
  80. static const char pszMe[] = "usbchr: ";
  81. static wait_queue_head_t wq_read;
  82. static wait_queue_head_t wq_write;
  83. static wait_queue_head_t wq_poll;
  84. /* Serialze multiple writers onto the transmit hardware
  85. .. since we sleep the writer during transmit to stay in
  86. .. sync. (Multiple writers don't make much sense, but..) */
  87. static DECLARE_MUTEX( xmit_sem );
  88. // size of usb DATA0/1 packets. 64 is standard maximum
  89. // for bulk transport, though most hosts seem to be able
  90. // to handle larger.
  91. #define TX_PACKET_SIZE 64
  92. #define RX_PACKET_SIZE 64
  93. #define RBUF_SIZE  (4*PAGE_SIZE)
  94. static struct wcirc_buf {
  95.   char *buf;
  96.   int in;
  97.   int out;
  98. } rx_ring = { NULL, 0, 0 };
  99. static struct {
  100.  unsigned long  cnt_rx_complete;
  101.  unsigned long  cnt_rx_errors;
  102.  unsigned long  bytes_rx;
  103.  unsigned long  cnt_tx_timeouts;
  104.  unsigned long  cnt_tx_errors;
  105.  unsigned long  bytes_tx;
  106. } charstats;
  107. static char * tx_buf = NULL;
  108. static char * packet_buffer = NULL;
  109. static int sending = 0;
  110. static int usb_ref_count = 0;
  111. static int last_tx_result = 0;
  112. static int last_rx_result = 0;
  113. static int last_tx_size = 0;
  114. static struct timer_list tx_timer;
  115. //////////////////////////////////////////////////////////////////////////////
  116. // Prototypes
  117. //////////////////////////////////////////////////////////////////////////////
  118. static char *  what_the_f( int e );
  119. static void  free_txrx_buffers( void );
  120. static void     twiddle_descriptors( void );
  121. static void     free_string_descriptors( void ) ;
  122. static int      usbc_open( struct inode *pInode, struct file *pFile );
  123. static void     rx_done_callback_packet_buffer( int flag, int size );
  124. static void     tx_timeout( unsigned long );
  125. static void     tx_done_callback( int flag, int size );
  126. static ssize_t  usbc_read( struct file *, char *, size_t, loff_t * );
  127. static ssize_t  usbc_write( struct file *, const char *, size_t, loff_t * );
  128. static unsigned int usbc_poll( struct file *pFile, poll_table * pWait );
  129. static int usbc_ioctl( struct inode *pInode, struct file *pFile,
  130.                        unsigned int nCmd, unsigned long argument );
  131. static int      usbc_close( struct inode *pInode, struct file *pFile );
  132. #ifdef CONFIG_SA1100_EXTENEX1
  133. static void     extenex_configured_notify_proc( void );
  134. #endif
  135. //////////////////////////////////////////////////////////////////////////////
  136. // Private Helpers
  137. //////////////////////////////////////////////////////////////////////////////
  138. static char * what_the_f( int e )
  139. {
  140.  char * p;
  141.  switch( e ) {
  142.  case 0:
  143.   p = "noErr";
  144.   break;
  145.  case -ENODEV:
  146.   p = "ENODEV - usb not in config state";
  147.   break;
  148.  case -EBUSY:
  149.   p = "EBUSY - another request on the hardware";
  150.   break;
  151.  case -EAGAIN:
  152.   p = "EAGAIN";
  153.   break;
  154.  case -EINTR:
  155.   p = "EINTR - interruptedn";
  156.   break;
  157.  case -EPIPE:
  158.   p = "EPIPE - zero length xfern";
  159.   break;
  160.  default:
  161.   p = "????";
  162.   break;
  163.  }
  164.  return p;
  165. }
  166. static void free_txrx_buffers( void )
  167. {
  168.  if ( rx_ring.buf != NULL ) {
  169.   kfree( rx_ring.buf );
  170.   rx_ring.buf = NULL;
  171.  }
  172.  if ( packet_buffer != NULL ) {
  173.   kfree( packet_buffer );
  174.   packet_buffer = NULL;
  175.  }
  176.  if ( tx_buf != NULL ) {
  177.   kfree( tx_buf );
  178.   tx_buf = NULL;
  179.  }
  180. }
  181. /* twiddle_descriptors()
  182.  * It is between open() and start(). Setup descriptors.
  183.  */
  184. static void twiddle_descriptors( void )
  185. {
  186.  desc_t * pDesc = pxa_usb_get_descriptor_ptr();
  187.  string_desc_t * pString;
  188.  pDesc->b.ep1.wMaxPacketSize = make_word_c( RX_PACKET_SIZE );
  189.  pDesc->b.ep1.bmAttributes   = USB_EP_BULK;
  190.  pDesc->b.ep2.wMaxPacketSize = make_word_c( TX_PACKET_SIZE );
  191.  pDesc->b.ep2.bmAttributes   = USB_EP_BULK;
  192.          if ( machine_is_extenex1() ) {
  193. #ifdef CONFIG_SA1100_EXTENEX1
  194.   pDesc->dev.idVendor = make_word_c( 0xC9F );
  195.   pDesc->dev.idProduct = 1;
  196.   pDesc->dev.bcdDevice = make_word_c( 0x0001 );
  197.   pDesc->b.cfg.bmAttributes = USB_CONFIG_SELFPOWERED;
  198.   pDesc->b.cfg.MaxPower = 0;
  199.   pString = pxa_usb_kmalloc_string_descriptor( "Extenex" );
  200.   if ( pString ) {
  201.    pxa_usb_set_string_descriptor( 1, pString );
  202.    pDesc->dev.iManufacturer = 1;
  203.   }
  204.   pString = pxa_usb_kmalloc_string_descriptor( "Handheld Theater" );
  205.   if ( pString ) {
  206.    pxa_usb_set_string_descriptor( 2, pString );
  207.    pDesc->dev.iProduct = 2;
  208.   }
  209.   pString = pxa_usb_kmalloc_string_descriptor( "00000000" );
  210.   if ( pString ) {
  211.    pxa_usb_set_string_descriptor( 3, pString );
  212.    pDesc->dev.iSerialNumber = 3;
  213.   }
  214.   pString = pxa_usb_kmalloc_string_descriptor( "HHT Bulk Transfer" );
  215.   if ( pString ) {
  216.    pxa_usb_set_string_descriptor( 4, pString );
  217.    pDesc->b.intf.iInterface = 4;
  218.   }
  219.   pxa_set_configured_callback( extenex_configured_notify_proc );
  220. #endif
  221.  }
  222. }
  223. static void free_string_descriptors( void )
  224. {
  225.  if ( machine_is_extenex1() ) {
  226.   string_desc_t * pString;
  227.   int i;
  228.   for( i = 1 ; i <= 4 ; i++ ) {
  229.    pString = pxa_usb_get_string_descriptor( i );
  230.    if ( pString )
  231. kfree( pString );
  232.   }
  233.  }
  234. }
  235. //////////////////////////////////////////////////////////////////////////////
  236. // ASYNCHRONOUS
  237. //////////////////////////////////////////////////////////////////////////////
  238. static  void kick_start_rx( void )
  239. {
  240.  if ( usb_ref_count ) {
  241.   int total_space  = CIRC_SPACE( rx_ring.in, rx_ring.out, RBUF_SIZE );
  242.   if ( total_space >= RX_PACKET_SIZE ) {
  243.    pxa_usb_recv( packet_buffer,
  244. RX_PACKET_SIZE,
  245. rx_done_callback_packet_buffer
  246.       );
  247.   }
  248.  }
  249. }
  250. /*
  251.  * rx_done_callback_packet_buffer()
  252.  * We have completed a DMA xfer into the temp packet buffer.
  253.  * Move to ring.
  254.  *
  255.  * flag values:
  256.  * on init,  -EAGAIN
  257.  * on reset, -EINTR
  258.  * on RPE, -EIO
  259.  * on short packet -EPIPE
  260.  */
  261. static void
  262. rx_done_callback_packet_buffer( int flag, int size )
  263. {
  264.  charstats.cnt_rx_complete++;
  265.  if ( flag == 0 || flag == -EPIPE ) {
  266.   size_t n;
  267.   charstats.bytes_rx += size;
  268.   n = CIRC_SPACE_TO_END( rx_ring.in, rx_ring.out, RBUF_SIZE );
  269.   n = MIN( n, size );
  270.   size -= n;
  271.   memcpy( &rx_ring.buf[ rx_ring.in ], packet_buffer, n );
  272.   rx_ring.in = (rx_ring.in + n) & (RBUF_SIZE-1);
  273.   memcpy( &rx_ring.buf[ rx_ring.in ], packet_buffer + n, size );
  274.   rx_ring.in = (rx_ring.in + size) & (RBUF_SIZE-1);
  275.   wake_up_interruptible( &wq_read );
  276.   wake_up_interruptible( &wq_poll );
  277.   last_rx_result = 0;
  278.   kick_start_rx();
  279.  } else if ( flag != -EAGAIN ) {
  280.   charstats.cnt_rx_errors++;
  281.   last_rx_result = flag;
  282.   wake_up_interruptible( &wq_read );
  283.   wake_up_interruptible( &wq_poll );
  284.  }
  285.  else  /* init, start a read */
  286.   kick_start_rx();
  287. }
  288. static void tx_timeout( unsigned long unused )
  289. {
  290. printk( "%stx timeoutn", pszMe );
  291. pxa_usb_send_reset();
  292. charstats.cnt_tx_timeouts++;
  293. }
  294. // on init, -EAGAIN
  295. // on reset, -EINTR
  296. // on TPE, -EIO
  297. static void tx_done_callback( int flags, int size )
  298. {
  299.  if ( flags == 0 )
  300.   charstats.bytes_tx += size;
  301.  else
  302.   charstats.cnt_tx_errors++;
  303.  last_tx_size = size;
  304.  last_tx_result = flags;
  305.  sending = 0;
  306.  wake_up_interruptible( &wq_write );
  307.  wake_up_interruptible( &wq_poll );
  308. }
  309. //////////////////////////////////////////////////////////////////////////////
  310. // Workers
  311. //////////////////////////////////////////////////////////////////////////////
  312. static int usbc_open( struct inode *pInode, struct file *pFile )
  313. {
  314.  int retval = 0;
  315.  PRINTK( KERN_DEBUG "%sopen()n", pszMe );
  316.  /* start usb core */
  317.  retval = pxa_usb_open( "usb-char" );
  318.  if ( retval ) return retval;
  319.  /* allocate memory */
  320.  if ( usb_ref_count == 0 ) {
  321.   tx_buf = (char*) kmalloc( TX_PACKET_SIZE, GFP_KERNEL | GFP_DMA );
  322.   if ( tx_buf == NULL ) {
  323.    printk( "%sARGHH! COULD NOT ALLOCATE TX BUFFERn", pszMe );
  324.    goto malloc_fail;
  325.   }
  326.   rx_ring.buf =
  327. (char*) kmalloc( RBUF_SIZE, GFP_KERNEL );
  328.   if ( rx_ring.buf == NULL ) {
  329.    printk( "%sARGHH! COULD NOT ALLOCATE RX BUFFERn", pszMe );
  330.    goto malloc_fail;
  331.   }
  332.   packet_buffer =
  333. (char*) kmalloc( RX_PACKET_SIZE, GFP_KERNEL | GFP_DMA  );
  334.   if ( packet_buffer == NULL ) {
  335.    printk( "%sARGHH! COULD NOT ALLOCATE RX PACKET BUFFERn", pszMe );
  336.    goto malloc_fail;
  337.   }
  338.   rx_ring.in = rx_ring.out = 0;
  339.   memset( &charstats, 0, sizeof( charstats ) );
  340.   sending = 0;
  341.   last_tx_result = 0;
  342.   last_tx_size = 0;
  343.  }
  344.  /* modify default descriptors */
  345.  twiddle_descriptors();
  346.  retval = pxa_usb_start();
  347.  if ( retval ) {
  348.   printk( "%sAGHH! Could not USB coren", pszMe );
  349.   free_txrx_buffers();
  350.   return retval;
  351.  }
  352.  usb_ref_count++;   /* must do _before_ kick_start() */
  353.  MOD_INC_USE_COUNT;
  354.  kick_start_rx();
  355.  return 0;
  356.  malloc_fail:
  357.  free_txrx_buffers();
  358.  return -ENOMEM;
  359. }
  360. /*
  361.  * Read endpoint. Note that you can issue a read to an
  362.  * unconfigured endpoint. Eventually, the host may come along
  363.  * and configure underneath this module and data will appear.
  364.  */
  365. static ssize_t usbc_read( struct file *pFile, char *pUserBuffer,
  366.                         size_t stCount, loff_t *pPos )
  367. {
  368.  ssize_t retval;
  369.  int flags;
  370.  DECLARE_WAITQUEUE( wait, current );
  371.  PRINTK( KERN_DEBUG "%sread()n", pszMe );
  372.  local_irq_save( flags );
  373.  if ( last_rx_result == 0 ) {
  374.   local_irq_restore( flags );
  375.  } else {  /* an error happended and receiver is paused */
  376.   local_irq_restore( flags );
  377.   last_rx_result = 0;
  378.   kick_start_rx();
  379.  }
  380.  add_wait_queue( &wq_read, &wait );
  381.  while( 1 ) {
  382.   ssize_t bytes_avail;
  383.   ssize_t bytes_to_end;
  384.   set_current_state( TASK_INTERRUPTIBLE );
  385.   /* snap ring buf state */
  386.   local_irq_save( flags );
  387.   bytes_avail  = CIRC_CNT( rx_ring.in, rx_ring.out, RBUF_SIZE );
  388.   bytes_to_end = CIRC_CNT_TO_END( rx_ring.in, rx_ring.out, RBUF_SIZE );
  389.   local_irq_restore( flags );
  390.   if ( bytes_avail != 0 ) {
  391.    ssize_t bytes_to_move = MIN( stCount, bytes_avail );
  392.    retval = 0; // will be bytes transfered
  393.    if ( bytes_to_move != 0 ) {
  394. size_t n = MIN( bytes_to_end, bytes_to_move );
  395. if ( copy_to_user( pUserBuffer,
  396.    &rx_ring.buf[ rx_ring.out ],
  397.    n ) ) {
  398.  retval = -EFAULT;
  399.  break;
  400. }
  401. bytes_to_move -= n;
  402.   retval += n;
  403. // might go 1 char off end, so wrap
  404. rx_ring.out = ( rx_ring.out + n ) & (RBUF_SIZE-1);
  405. if ( copy_to_user( pUserBuffer + n,
  406.    &rx_ring.buf[ rx_ring.out ],
  407.    bytes_to_move )
  408.  ) {
  409.  retval = -EFAULT;
  410.  break;
  411. }
  412. rx_ring.out += bytes_to_move; // cannot wrap
  413. retval += bytes_to_move;
  414. kick_start_rx();
  415.    }
  416.    break;
  417.   }
  418.   else if ( last_rx_result ) {
  419.    retval = last_rx_result;
  420.    break;
  421.   }
  422.   else if ( pFile->f_flags & O_NONBLOCK ) {  // no data, can't sleep
  423.    retval = -EAGAIN;
  424.    break;
  425.   }
  426.   else if ( signal_pending( current ) ) {   // no data, can sleep, but signal
  427.    retval = -ERESTARTSYS;
  428.    break;
  429.   }
  430.   schedule();     // no data, can sleep
  431.  }
  432.  set_current_state( TASK_RUNNING );
  433.  remove_wait_queue( &wq_read, &wait );
  434.  if ( retval < 0 )
  435.   printk( "%sread error %d - %sn", pszMe, retval, what_the_f( retval ) );
  436.  return retval;
  437. }
  438. /*
  439.  * Write endpoint. This routine attempts to break the passed in buffer
  440.  * into usb DATA0/1 packet size chunks and send them to the host.
  441.  * (The lower-level driver tries to do this too, but easier for us
  442.  * to manage things here.)
  443.  *
  444.  * We are at the mercy of the host here, in that it must send an IN
  445.  * token to us to pull this data back, so hopefully some higher level
  446.  * protocol is expecting traffic to flow in that direction so the host
  447.  * is actually polling us. To guard against hangs, a 5 second timeout
  448.  * is used.
  449.  *
  450.  * This routine takes some care to only report bytes sent that have
  451.  * actually made it across the wire. Thus we try to stay in lockstep
  452.  * with the completion routine and only have one packet on the xmit
  453.  * hardware at a time. Multiple simultaneous writers will get
  454.  * "undefined" results.
  455.  *
  456.   */
  457. static ssize_t  usbc_write( struct file *pFile, const char * pUserBuffer,
  458.  size_t stCount, loff_t *pPos )
  459. {
  460.  ssize_t retval = 0;
  461.  ssize_t stSent = 0;
  462.  DECLARE_WAITQUEUE( wait, current );
  463.  PRINTK( KERN_DEBUG "%swrite() %d bytesn", pszMe, stCount );
  464.  down( &xmit_sem );  // only one thread onto the hardware at a time
  465.  while( stCount != 0 && retval == 0 ) {
  466.   int nThisTime  = MIN( TX_PACKET_SIZE, stCount );
  467.   copy_from_user( tx_buf, pUserBuffer, nThisTime );
  468.   sending = nThisTime;
  469.     retval = pxa_usb_send( tx_buf, nThisTime, tx_done_callback );
  470.   if ( retval < 0 ) {
  471.    char * p = what_the_f( retval );
  472.    printk( "%sCould not queue xmission. rc=%d - %sn",
  473.    pszMe, retval, p );
  474.    sending = 0;
  475.    break;
  476.   }
  477.   /* now have something on the diving board */
  478.   add_wait_queue( &wq_write, &wait );
  479.   tx_timer.expires = jiffies + ( HZ * 5 );
  480.   add_timer( &tx_timer );
  481.   while( 1 ) {
  482.    set_current_state( TASK_INTERRUPTIBLE );
  483.    if ( sending == 0 ) {  /* it jumped into the pool */
  484. del_timer( &tx_timer );
  485. retval = last_tx_result;
  486. if ( retval == 0 ) {
  487.  stSent  += last_tx_size;
  488.  pUserBuffer += last_tx_size;
  489.  stCount     -= last_tx_size;
  490. }
  491. else
  492.  printk( "%sxmission error rc=%d - %sn",
  493.  pszMe, retval, what_the_f(retval) );
  494. break;
  495.    }
  496.    else if ( signal_pending( current ) ) {
  497. del_timer( &tx_timer );
  498. printk( "%ssignaln", pszMe  );
  499. retval = -ERESTARTSYS;
  500. break;
  501.    }
  502.    schedule();
  503.   }
  504.   set_current_state( TASK_RUNNING );
  505.   remove_wait_queue( &wq_write, &wait );
  506.  }
  507.  up( &xmit_sem );
  508.  if ( 0 == retval )
  509.   retval = stSent;
  510.  return retval;
  511. }
  512. static unsigned int usbc_poll( struct file *pFile, poll_table * pWait )
  513. {
  514.  unsigned int retval = 0;
  515.  PRINTK( KERN_DEBUG "%poll()n", pszMe );
  516.  poll_wait( pFile, &wq_poll, pWait );
  517.  if ( CIRC_CNT( rx_ring.in, rx_ring.out, RBUF_SIZE ) )
  518.   retval |= POLLIN | POLLRDNORM;
  519.  if ( pxa_usb_xmitter_avail() )
  520.   retval |= POLLOUT | POLLWRNORM;
  521.  return retval;
  522. }
  523. static int usbc_ioctl( struct inode *pInode, struct file *pFile,
  524.                        unsigned int nCmd, unsigned long argument )
  525. {
  526.  int retval = 0;
  527.  switch( nCmd ) {
  528.  case USBC_IOC_FLUSH_RECEIVER:
  529.   pxa_usb_recv_reset();
  530.   rx_ring.in = rx_ring.out = 0;
  531.   break;
  532.  case USBC_IOC_FLUSH_TRANSMITTER:
  533.   pxa_usb_send_reset();
  534.   break;
  535.  case USBC_IOC_FLUSH_ALL:
  536.   pxa_usb_recv_reset();
  537.   rx_ring.in = rx_ring.out = 0;
  538.   pxa_usb_send_reset();
  539.   break;
  540.  default:
  541.   retval = -ENOIOCTLCMD;
  542.   break;
  543.  }
  544.  return retval;
  545. }
  546. static int usbc_close( struct inode *pInode, struct file * pFile )
  547. {
  548. PRINTK( KERN_DEBUG "%sclose()n", pszMe );
  549. if ( --usb_ref_count == 0 ) {
  550.  down( &xmit_sem );
  551.  pxa_usb_stop();
  552.  free_txrx_buffers();
  553.  free_string_descriptors();
  554.  del_timer( &tx_timer );
  555.  pxa_usb_close();
  556.  up( &xmit_sem );
  557. }
  558.     MOD_DEC_USE_COUNT;
  559.     return 0;
  560. }
  561. #ifdef CONFIG_SA1100_EXTENEX1
  562. #include "../../../drivers/char/ex_gpio.h"
  563. void extenex_configured_notify_proc( void )
  564. {
  565.  if ( exgpio_play_string( "440,1:698,1" ) == -EAGAIN )
  566.   printk( "%sWanted to BEEP but ex_gpio not openn", pszMe );
  567. }
  568. #endif
  569. //////////////////////////////////////////////////////////////////////////////
  570. // Initialization
  571. //////////////////////////////////////////////////////////////////////////////
  572. static struct file_operations usbc_fops = {
  573. owner:      THIS_MODULE,
  574. open: usbc_open,
  575. read: usbc_read,
  576. write: usbc_write,
  577. poll: usbc_poll,
  578. ioctl: usbc_ioctl,
  579. release: usbc_close,
  580. };
  581. static struct miscdevice usbc_misc_device = {
  582.     USBC_MINOR, "usb_char", &usbc_fops
  583. };
  584. /*
  585.  * usbc_init()
  586.  */
  587. int __init usbc_init( void )
  588. {
  589.  int rc;
  590.  if ( (rc = misc_register( &usbc_misc_device )) != 0 ) {
  591.   printk( KERN_WARNING "%sCould not register device 10, "
  592.   "%d. (%d)n", pszMe, USBC_MINOR, rc );
  593.   return -EBUSY;
  594.  }
  595.  // initialize wait queues
  596.  init_waitqueue_head( &wq_read );
  597.  init_waitqueue_head( &wq_write );
  598.  init_waitqueue_head( &wq_poll );
  599.  // initialize tx timeout timer
  600.  init_timer( &tx_timer );
  601.  tx_timer.function = tx_timeout;
  602.   printk( KERN_INFO "USB Function Character Driver Interface"
  603.   " - %s, (C) 2001, Extenex Corp.n", VERSION
  604.    );
  605.  return rc;
  606. }
  607. void __exit usbc_exit( void )
  608. {
  609. }
  610. EXPORT_NO_SYMBOLS;
  611. module_init(usbc_init);
  612. module_exit(usbc_exit);
  613. // end: usb-char.c