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

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * (C) Copyright 2000-2001 MIZI Research, Inc.
  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 S3C2410 USB function
  21.  * driver.
  22.  */
  23. #include <linux/module.h>
  24. #include <linux/config.h>
  25. #include <linux/miscdevice.h>
  26. #include <linux/slab.h>
  27. #include <linux/init.h>
  28. #include <linux/cache.h>
  29. #include <linux/poll.h>
  30. #include <linux/circ_buf.h>
  31. #include <linux/timer.h>
  32. #include <asm/io.h>
  33. #include <asm/semaphore.h>
  34. #include <asm/proc/page.h>
  35. #include <asm/mach-types.h>
  36. #include "usb-char.h"
  37. #include "s3c2410_usb.h"
  38. #ifdef CONFIG_MIZI
  39. #include <asm/irq.h>
  40. #ifdef CONFIG_PM
  41. #include <linux/pm.h>
  42. static struct pm_dev *usb_char_pm_dev;
  43. #endif
  44. #endif
  45. //////////////////////////////////////////////////////////////////////////////
  46. // Driver  Options
  47. //////////////////////////////////////////////////////////////////////////////
  48. #ifdef CONFIG_MIZI
  49. #define VERSION "0.5"
  50. #define LINUETTE_VENDOR_ID 0x49f
  51. #define LINUETTE_PRODUCT_ID 0x505A
  52. #define LINUETTE_REV_NUM 1
  53.  
  54. #define USB_CHAR_MANUFACTURE "MIZI Research Inc."
  55. #define USB_CHAR_FOR_WHAT "linu@usb"
  56. #define USB_CHAR_BUILD_DATE "20020115"
  57. #define USB_CHAR_INTERFACE "Bulk Transfer"
  58. #else
  59. #define VERSION "0.4"
  60. #endif
  61. //#define VERBOSITY 1
  62. #if VERBOSITY
  63. # define PRINTK(a...) printk(__FILE__":"__FUNCTION__"(): " ##a)
  64. #else
  65. # define PRINTK(a...) (void)(0)
  66. #endif
  67. //////////////////////////////////////////////////////////////////////////////
  68. // Globals - Macros - Enums - Structures
  69. //////////////////////////////////////////////////////////////////////////////
  70. #ifndef MIN
  71. #define MIN( a, b ) ((a)<(b)?(a):(b))
  72. #endif
  73. typedef int bool; enum { false = 0, true = 1 };
  74. static const char pszMe[] = "usbchr: ";
  75. static wait_queue_head_t wq_read;
  76. static wait_queue_head_t wq_write;
  77. static wait_queue_head_t wq_poll;
  78. /* Serialze multiple writers onto the transmit hardware
  79. .. since we sleep the writer during transmit to stay in
  80. .. sync. (Multiple writers don't make much sense, but..) */
  81. static DECLARE_MUTEX( xmit_sem );
  82. // size of usb DATA0/1 packets. 64 is standard maximum
  83. // for bulk transport, though most hosts seem to be able
  84. // to handle larger.
  85. #define TX_PACKET_SIZE 64
  86. #define RX_PACKET_SIZE 64
  87. #define RBUF_SIZE  (4*PAGE_SIZE)
  88. static struct wcirc_buf {
  89.   char *buf;
  90.   int in;
  91.   int out;
  92. } rx_ring = { NULL, 0, 0 };
  93. static struct {
  94.  unsigned long  cnt_rx_complete;
  95.  unsigned long  cnt_rx_errors;
  96.  unsigned long  bytes_rx;
  97.  unsigned long  cnt_tx_timeouts;
  98.  unsigned long  cnt_tx_errors;
  99.  unsigned long  bytes_tx;
  100. } charstats;
  101. static char * tx_buf = NULL;
  102. static char * packet_buffer = NULL;
  103. static int sending = 0;
  104. static int usb_ref_count = 0;
  105. static int last_tx_result = 0;
  106. static int last_rx_result = 0;
  107. static int last_tx_size = 0;
  108. static struct timer_list tx_timer;
  109. //////////////////////////////////////////////////////////////////////////////
  110. // Prototypes
  111. //////////////////////////////////////////////////////////////////////////////
  112. #ifndef CONFIG_MIZI
  113. static char *  what_the_f( int e );
  114. #endif
  115. static void  free_txrx_buffers( void );
  116. static void     twiddle_descriptors( void );
  117. static void     free_string_descriptors( void ) ;
  118. static int      usbc_open( struct inode *pInode, struct file *pFile );
  119. static void     rx_done_callback_packet_buffer( int flag, int size );
  120. static void     tx_timeout( unsigned long );
  121. static void     tx_done_callback( int flag, int size );
  122. static ssize_t  usbc_read( struct file *, char *, size_t, loff_t * );
  123. static ssize_t  usbc_write( struct file *, const char *, size_t, loff_t * );
  124. static unsigned int usbc_poll( struct file *pFile, poll_table * pWait );
  125. static int usbc_ioctl( struct inode *pInode, struct file *pFile,
  126.                        unsigned int nCmd, unsigned long argument );
  127. static int      usbc_close( struct inode *pInode, struct file *pFile );
  128. #ifdef CONFIG_S3C2410_EXTENEX1
  129. static void     extenex_configured_notify_proc( void );
  130. #endif
  131. #ifdef CONFIG_MIZI
  132. static int usbc_activate(void);
  133. static void usbc_deactivate(void);
  134. #endif
  135. //////////////////////////////////////////////////////////////////////////////
  136. // Private Helpers
  137. //////////////////////////////////////////////////////////////////////////////
  138. #if defined(CONFIG_PM) && defined(CONFIG_MIZI)
  139. extern void usbctl_suspend(void);
  140. extern void usbctl_resume(void);
  141. static int
  142. usbchar_pm_callback(struct pm_dev *pm_dev, pm_request_t req, void *data)
  143. {
  144. PRINTK("pm_callback: %dn", req);
  145. switch (req) {
  146. case PM_RESUME:    
  147. usbctl_resume();
  148. usbc_activate();
  149. PRINTK("usb-char wakeup...");
  150. break;
  151. case PM_SUSPEND:   
  152. usbc_deactivate();
  153. usbctl_suspend();
  154. PRINTK("usb-char sleep...");
  155. break;
  156. }
  157. PRINTK("donen");
  158.  
  159. return 0;
  160. }
  161. #endif
  162. #ifndef CONFIG_MIZI
  163. static char * what_the_f( int e )
  164. {
  165.  char * p;
  166.  switch( e ) {
  167.  case 0:
  168.   p = "noErr";
  169.   break;
  170.  case -ENODEV:
  171.   p = "ENODEV - usb not in config state";
  172.   break;
  173.  case -EBUSY:
  174.   p = "EBUSY - another request on the hardware";
  175.   break;
  176.  case -EAGAIN:
  177.   p = "EAGAIN";
  178.   break;
  179.  case -EINTR:
  180.   p = "EINTR - interruptedn";
  181.   break;
  182.  case -EPIPE:
  183.   p = "EPIPE - zero length xfern";
  184.   break;
  185.  default:
  186.   p = "????";
  187.   break;
  188.  }
  189.  return p;
  190. }
  191. #endif
  192. static void free_txrx_buffers( void )
  193. {
  194. PRINTK("n");
  195.  if ( rx_ring.buf != NULL ) {
  196.   kfree( rx_ring.buf );
  197.   rx_ring.buf = NULL;
  198.  }
  199.  if ( packet_buffer != NULL ) {
  200.   kfree( packet_buffer );
  201.   packet_buffer = NULL;
  202.  }
  203.  if ( tx_buf != NULL ) {
  204.   kfree( tx_buf );
  205.   tx_buf = NULL;
  206.  }
  207. }
  208. /* twiddle_descriptors()
  209.  * It is between open() and start(). Setup descriptors.
  210.  */
  211. static void twiddle_descriptors( void )
  212. {
  213.  desc_t * pDesc = s3c2410_usb_get_descriptor_ptr();
  214.  string_desc_t * pString;
  215. PRINTK("n");
  216.  pDesc->b.ep1.wMaxPacketSize = make_word_c( RX_PACKET_SIZE );
  217.  pDesc->b.ep1.bmAttributes   = USB_EP_BULK;
  218.  pDesc->b.ep2.wMaxPacketSize = make_word_c( TX_PACKET_SIZE );
  219.  pDesc->b.ep2.bmAttributes   = USB_EP_BULK;
  220. #ifdef CONFIG_MIZI
  221. pDesc->dev.idVendor = LINUETTE_VENDOR_ID;
  222. pDesc->dev.idProduct = LINUETTE_PRODUCT_ID;
  223. pDesc->dev.bcdDevice = LINUETTE_REV_NUM;
  224. pDesc->b.cfg.bmAttributes = USB_CONFIG_SELFPOWERED;
  225. pDesc->b.cfg.MaxPower = 0;
  226. if (s3c2410_usb_get_string_descriptor(4)) return;
  227. pString = s3c2410_usb_kmalloc_string_descriptor( USB_CHAR_MANUFACTURE);
  228. if ( pString ) {
  229. s3c2410_usb_set_string_descriptor( 1, pString );
  230. pDesc->dev.iManufacturer = 1;
  231. }
  232. pString = s3c2410_usb_kmalloc_string_descriptor( USB_CHAR_FOR_WHAT );
  233. if ( pString ) {
  234. s3c2410_usb_set_string_descriptor( 2, pString );
  235. pDesc->dev.iProduct = 2;
  236. }
  237. pString = s3c2410_usb_kmalloc_string_descriptor( USB_CHAR_BUILD_DATE );
  238. if ( pString ) {
  239. s3c2410_usb_set_string_descriptor( 3, pString );
  240. pDesc->dev.iSerialNumber = 3;
  241. }
  242. pString = s3c2410_usb_kmalloc_string_descriptor( USB_CHAR_INTERFACE );
  243. if ( pString ) {
  244. s3c2410_usb_set_string_descriptor( 4, pString );
  245. pDesc->b.intf.iInterface = 4;
  246. }
  247. #endif
  248. }
  249. static void free_string_descriptors( void )
  250. {
  251. PRINTK("n");
  252.  if ( machine_is_extenex1() ) {
  253.   string_desc_t * pString;
  254.   int i;
  255.   for( i = 1 ; i <= 4 ; i++ ) {
  256.    pString = s3c2410_usb_get_string_descriptor( i );
  257.    if ( pString )
  258. kfree( pString );
  259.   }
  260.  }
  261. #ifdef CONFIG_MIZI
  262. {
  263. string_desc_t * pString;
  264. int i;
  265. for( i = 1 ; i <= 4 ; i++ ) {
  266. pString = s3c2410_usb_get_string_descriptor( i );
  267. if ( pString )
  268. kfree( pString );
  269. s3c2410_usb_set_string_descriptor( i , NULL);
  270. }
  271. }
  272. #endif
  273. }
  274. //////////////////////////////////////////////////////////////////////////////
  275. // ASYNCHRONOUS
  276. //////////////////////////////////////////////////////////////////////////////
  277. static  void kick_start_rx( void )
  278. {
  279. PRINTK("n");
  280. #if defined(CONFIG_MIZI)
  281.    {
  282. #else
  283.     // PRINTK("i'm not  MIZI - %dn", usb_ref_count);
  284.  if ( usb_ref_count ) {
  285. #endif
  286.   int total_space  = CIRC_SPACE( rx_ring.in, rx_ring.out, RBUF_SIZE );
  287. //       PRINTK("total_space = %d, %dn", total_space, RX_PACKET_SIZE);
  288.   if ( total_space >= RX_PACKET_SIZE ) {
  289.    s3c2410_usb_recv( packet_buffer,
  290. RX_PACKET_SIZE,
  291. rx_done_callback_packet_buffer
  292.       );
  293.   }
  294.  }
  295. }
  296. /*
  297.  * rx_done_callback_packet_buffer()
  298.  * We have completed a DMA xfer into the temp packet buffer.
  299.  * Move to ring.
  300.  *
  301.  * flag values:
  302.  * on init,  -EAGAIN
  303.  * on reset, -EINTR
  304.  * on RPE, -EIO
  305.  * on short packet -EPIPE
  306.  */
  307. static void
  308. rx_done_callback_packet_buffer( int flag, int size )
  309. {
  310.  charstats.cnt_rx_complete++;
  311. PRINTK("n");
  312.  if ( flag == 0 || flag == -EPIPE ) {
  313.   size_t n;
  314.   charstats.bytes_rx += size;
  315.   n = CIRC_SPACE_TO_END( rx_ring.in, rx_ring.out, RBUF_SIZE );
  316.   n = MIN( n, size );
  317.   size -= n;
  318.   memcpy( &rx_ring.buf[ rx_ring.in ], packet_buffer, n );
  319.   rx_ring.in = (rx_ring.in + n) & (RBUF_SIZE-1);
  320.   memcpy( &rx_ring.buf[ rx_ring.in ], packet_buffer + n, size );
  321.   rx_ring.in = (rx_ring.in + size) & (RBUF_SIZE-1);
  322.   wake_up_interruptible( &wq_read );
  323.   wake_up_interruptible( &wq_poll );
  324.   last_rx_result = 0;
  325.   kick_start_rx();
  326.  } else if ( flag != -EAGAIN ) {
  327.   charstats.cnt_rx_errors++;
  328.   last_rx_result = flag;
  329.   wake_up_interruptible( &wq_read );
  330.   wake_up_interruptible( &wq_poll );
  331.  }
  332.  else  /* init, start a read */
  333.   kick_start_rx();
  334. }
  335. static void tx_timeout( unsigned long unused )
  336. {
  337. PRINTK( "%stx timeoutn", pszMe );
  338. s3c2410_usb_send_reset();
  339. charstats.cnt_tx_timeouts++;
  340. }
  341. // on init, -EAGAIN
  342. // on reset, -EINTR
  343. // on TPE, -EIO
  344. static void tx_done_callback( int flags, int size )
  345. {
  346. PRINTK("n");
  347.  if ( flags == 0 )
  348.   charstats.bytes_tx += size;
  349.  else
  350.   charstats.cnt_tx_errors++;
  351.  last_tx_size = size;
  352.  last_tx_result = flags;
  353.  sending = 0;
  354.  wake_up_interruptible( &wq_write );
  355.  wake_up_interruptible( &wq_poll );
  356. }
  357. //////////////////////////////////////////////////////////////////////////////
  358. // Workers
  359. //////////////////////////////////////////////////////////////////////////////
  360. #ifdef CONFIG_MIZI
  361. static void usbc_alloc_mem(void)
  362. {
  363. PRINTK("n");
  364. tx_buf = (char*) kmalloc( TX_PACKET_SIZE, GFP_KERNEL | GFP_DMA );
  365. if ( tx_buf == NULL ) {
  366. PRINTK( "%sARGHH! COULD NOT ALLOCATE TX BUFFERn", pszMe );
  367. }
  368. rx_ring.buf = (char*) kmalloc( RBUF_SIZE, GFP_KERNEL );
  369. if ( rx_ring.buf == NULL ) {
  370. PRINTK( "%sARGHH! COULD NOT ALLOCATE RX BUFFERn", pszMe );
  371. }
  372. packet_buffer = (char*) kmalloc( RX_PACKET_SIZE, GFP_KERNEL | GFP_DMA );
  373. if ( packet_buffer == NULL ) {
  374. PRINTK( "%sARGHH! COULD NOT ALLOCATE RX PACKET BUFFERn",pszMe);
  375. }
  376. //usbc_ioctl(0, 0, USBC_IOC_FLUSH_ALL, 0);
  377. }
  378. #endif
  379. static int usbc_open( struct inode *pInode, struct file *pFile )
  380. {
  381.  MOD_INC_USE_COUNT;
  382.  kick_start_rx();
  383.  return 0;
  384. }
  385. /*
  386.  * Read endpoint. Note that you can issue a read to an
  387.  * unconfigured endpoint. Eventually, the host may come along
  388.  * and configure underneath this module and data will appear.
  389.  */
  390. static ssize_t usbc_read( struct file *pFile, char *pUserBuffer,
  391.                         size_t stCount, loff_t *pPos )
  392. {
  393.  ssize_t retval;
  394.  int flags;
  395.  DECLARE_WAITQUEUE( wait, current );
  396. // PRINTK( "count=%d", stCount);
  397.  local_irq_save( flags );
  398.  if ( last_rx_result == 0 ) {
  399.   local_irq_restore( flags );
  400.  } else {  /* an error happended and receiver is paused */
  401.   local_irq_restore( flags );
  402.   last_rx_result = 0;
  403.   kick_start_rx();
  404.  }
  405.  add_wait_queue( &wq_read, &wait );
  406.  while( 1 ) {
  407.   ssize_t bytes_avail;
  408.   ssize_t bytes_to_end;
  409.   set_current_state( TASK_INTERRUPTIBLE );
  410.   /* snap ring buf state */
  411.   local_irq_save( flags );
  412.   bytes_avail  = CIRC_CNT( rx_ring.in, rx_ring.out, RBUF_SIZE );
  413.   bytes_to_end = CIRC_CNT_TO_END( rx_ring.in, rx_ring.out, RBUF_SIZE );
  414.   local_irq_restore( flags );
  415.   if ( bytes_avail != 0 ) {
  416.    ssize_t bytes_to_move = MIN( stCount, bytes_avail );
  417.    retval = 0; // will be bytes transfered
  418.    if ( bytes_to_move != 0 ) {
  419. size_t n = MIN( bytes_to_end, bytes_to_move );
  420. if ( copy_to_user( pUserBuffer,
  421.    &rx_ring.buf[ rx_ring.out ],
  422.    n ) ) {
  423.  retval = -EFAULT;
  424.  break;
  425. }
  426. bytes_to_move -= n;
  427.   retval += n;
  428. // might go 1 char off end, so wrap
  429. rx_ring.out = ( rx_ring.out + n ) & (RBUF_SIZE-1);
  430. if ( copy_to_user( pUserBuffer + n,
  431.    &rx_ring.buf[ rx_ring.out ],
  432.    bytes_to_move )
  433.  ) {
  434.  retval = -EFAULT;
  435.  break;
  436. }
  437. rx_ring.out += bytes_to_move; // cannot wrap
  438. retval += bytes_to_move;
  439. kick_start_rx();
  440.    }
  441.    break;
  442.   }
  443.   else if ( last_rx_result ) {
  444.    retval = last_rx_result;
  445.    break;
  446.   }
  447.   else if ( pFile->f_flags & O_NONBLOCK ) {  // no data, can't sleep
  448.    retval = -EAGAIN;
  449.    break;
  450.   }
  451.   else if ( signal_pending( current ) ) {   // no data, can sleep, but signal
  452.    retval = -ERESTARTSYS;
  453.    break;
  454.   }
  455.   schedule();     // no data, can sleep
  456.  }
  457.  set_current_state( TASK_RUNNING );
  458.  remove_wait_queue( &wq_read, &wait );
  459. #ifndef CONFIG_MIZI
  460.  if ( retval < 0 )
  461.   printk( "%sread error %d - %sn", pszMe, retval, what_the_f( retval ) );
  462. #endif
  463.  return retval;
  464. }
  465. /*
  466.  * Write endpoint. This routine attempts to break the passed in buffer
  467.  * into usb DATA0/1 packet size chunks and send them to the host.
  468.  * (The lower-level driver tries to do this too, but easier for us
  469.  * to manage things here.)
  470.  *
  471.  * We are at the mercy of the host here, in that it must send an IN
  472.  * token to us to pull this data back, so hopefully some higher level
  473.  * protocol is expecting traffic to flow in that direction so the host
  474.  * is actually polling us. To guard against hangs, a 5 second timeout
  475.  * is used.
  476.  *
  477.  * This routine takes some care to only report bytes sent that have
  478.  * actually made it across the wire. Thus we try to stay in lockstep
  479.  * with the completion routine and only have one packet on the xmit
  480.  * hardware at a time. Multiple simultaneous writers will get
  481.  * "undefined" results.
  482.  *
  483.   */
  484. static ssize_t  usbc_write( struct file *pFile, const char * pUserBuffer,
  485.  size_t stCount, loff_t *pPos )
  486. {
  487.  ssize_t retval = 0;
  488.  ssize_t stSent = 0;
  489.  DECLARE_WAITQUEUE( wait, current );
  490.  PRINTK( KERN_DEBUG "%swrite() %d bytesn", pszMe, stCount );
  491.  down( &xmit_sem );  // only one thread onto the hardware at a time
  492.  while( stCount != 0 && retval == 0 ) {
  493.   int nThisTime  = MIN( TX_PACKET_SIZE, stCount );
  494.   copy_from_user( tx_buf, pUserBuffer, nThisTime );
  495.   sending = nThisTime;
  496.     retval = s3c2410_usb_send( tx_buf, nThisTime, tx_done_callback );
  497.   if ( retval < 0 ) {
  498. #ifndef CONFIG_MIZI
  499.    char * p = what_the_f( retval );
  500.    printk( "%sCould not queue xmission. rc=%d - %sn",
  501.    pszMe, retval, p );
  502. #endif
  503.    sending = 0;
  504.    break;
  505.   }
  506.   /* now have something on the diving board */
  507.   add_wait_queue( &wq_write, &wait );
  508.   tx_timer.expires = jiffies + ( HZ * 5 );
  509.   add_timer( &tx_timer );
  510.   while( 1 ) {
  511.    set_current_state( TASK_INTERRUPTIBLE );
  512.    if ( sending == 0 ) {  /* it jumped into the pool */
  513. del_timer( &tx_timer );
  514. retval = last_tx_result;
  515. if ( retval == 0 ) {
  516.  stSent  += last_tx_size;
  517.  pUserBuffer += last_tx_size;
  518.  stCount     -= last_tx_size;
  519. }
  520. #ifndef CONFIG_MIZI
  521. else
  522.  printk( "%sxmission error rc=%d - %sn",
  523.  pszMe, retval, what_the_f(retval) );
  524. #endif
  525. break;
  526.    }
  527.    else if ( signal_pending( current ) ) {
  528. del_timer( &tx_timer );
  529. PRINTK( "%ssignaln", pszMe  );
  530. retval = -ERESTARTSYS;
  531. break;
  532.    }
  533.    schedule();
  534.   }
  535.   set_current_state( TASK_RUNNING );
  536.   remove_wait_queue( &wq_write, &wait );
  537.  }
  538.  up( &xmit_sem );
  539.  if ( 0 == retval )
  540.   retval = stSent;
  541.  return retval;
  542. }
  543. static unsigned int usbc_poll( struct file *pFile, poll_table * pWait )
  544. {
  545.  unsigned int retval = 0;
  546.  PRINTK( KERN_DEBUG "%poll()n", pszMe );
  547.  poll_wait( pFile, &wq_poll, pWait );
  548.  if ( CIRC_CNT( rx_ring.in, rx_ring.out, RBUF_SIZE ) )
  549.   retval |= POLLIN | POLLRDNORM;
  550.  if ( s3c2410_usb_xmitter_avail() )
  551.   retval |= POLLOUT | POLLWRNORM;
  552.  return retval;
  553. }
  554. static int usbc_ioctl( struct inode *pInode, struct file *pFile,
  555.                        unsigned int nCmd, unsigned long argument )
  556. {
  557.  int retval = 0;
  558.  switch( nCmd ) {
  559.  case USBC_IOC_FLUSH_RECEIVER:
  560.   s3c2410_usb_recv_reset();
  561.   rx_ring.in = rx_ring.out = 0;
  562.   break;
  563.  case USBC_IOC_FLUSH_TRANSMITTER:
  564.   s3c2410_usb_send_reset();
  565.   break;
  566.  case USBC_IOC_FLUSH_ALL:
  567.   s3c2410_usb_recv_reset();
  568.   rx_ring.in = rx_ring.out = 0;
  569.   s3c2410_usb_send_reset();
  570.   break;
  571.  default:
  572.   retval = -ENOIOCTLCMD;
  573.   break;
  574.  }
  575.  return retval;
  576. }
  577. #ifdef CONFIG_MIZI
  578. static int
  579. usbc_activate(void)
  580. {
  581. int retval = 0;
  582. PRINTK("n");
  583. /* start usb core */
  584. retval = s3c2410_usb_open( "usb-char" );
  585. twiddle_descriptors();
  586. retval = s3c2410_usb_start();
  587. if ( retval ) {
  588. PRINTK( "%sAGHH! Could not USB coren", pszMe );
  589. free_txrx_buffers();
  590. return retval;
  591. }
  592. usb_ref_count++;   /* must do _before_ kick_start() */
  593. kick_start_rx();
  594. return 0;
  595. }
  596. static void
  597. usbc_deactivate(void)
  598. {
  599. PRINTK("n");
  600. down( &xmit_sem );
  601. s3c2410_usb_stop();
  602. del_timer( &tx_timer );
  603. s3c2410_usb_close();
  604. up( &xmit_sem );
  605. }
  606. #endif
  607. static int usbc_close( struct inode *pInode, struct file * pFile )
  608. {
  609. PRINTK( KERN_DEBUG "%sclose()n", pszMe );
  610. #ifdef CONFIG_MIZI
  611. --usb_ref_count;
  612. #else
  613. if ( --usb_ref_count == 0 ) {
  614.  down( &xmit_sem );
  615.  s3c2410_usb_stop();
  616.  free_txrx_buffers();
  617.  free_string_descriptors();
  618.  del_timer( &tx_timer );
  619.  s3c2410_usb_close();
  620.  up( &xmit_sem );
  621. }
  622. #endif
  623.     MOD_DEC_USE_COUNT;
  624.     return 0;
  625. }
  626. //////////////////////////////////////////////////////////////////////////////
  627. // Initialization
  628. //////////////////////////////////////////////////////////////////////////////
  629. static struct file_operations usbc_fops = {
  630. owner:      THIS_MODULE,
  631. open: usbc_open,
  632. read: usbc_read,
  633. write: usbc_write,
  634. poll: usbc_poll,
  635. ioctl: usbc_ioctl,
  636. release: usbc_close,
  637. };
  638. static struct miscdevice usbc_misc_device = {
  639.     USBC_MINOR, "usb_char", &usbc_fops
  640. };
  641. /*
  642.  * usbc_init()
  643.  */
  644. int __init usbc_init( void )
  645. {
  646.  int rc;
  647. #if !defined( CONFIG_ARCH_S3C2410 )
  648.  return -ENODEV;
  649. #endif
  650.  if ( (rc = misc_register( &usbc_misc_device )) != 0 ) {
  651.   printk( KERN_WARNING "%sCould not register device 10, "
  652.   "%d. (%d)n", pszMe, USBC_MINOR, rc );
  653.   return -EBUSY;
  654.  }
  655.  // initialize wait queues
  656.  init_waitqueue_head( &wq_read );
  657.  init_waitqueue_head( &wq_write );
  658.  init_waitqueue_head( &wq_poll );
  659.  // initialize tx timeout timer
  660.  init_timer( &tx_timer );
  661.  tx_timer.function = tx_timeout;
  662. #ifdef CONFIG_MIZI
  663. memset( &charstats, 0, sizeof( charstats ) );
  664. sending = 0;
  665. last_tx_result = 0;
  666. last_tx_size = 0;
  667. #endif
  668. printk( KERN_INFO "USB Function Character Driver Interface"
  669. " - %s, (C) 2001, Extenex Corp.n", VERSION);
  670.  
  671. #ifdef CONFIG_MIZI
  672. #ifdef CONFIG_PM
  673. usb_char_pm_dev = pm_register(PM_SYS_DEV, PM_SYS_MISC,
  674.       usbchar_pm_callback);
  675. #endif
  676. usbc_alloc_mem();
  677. usbc_activate();
  678. #endif
  679.  return rc;
  680. }
  681. void __exit usbc_exit( void )
  682. {
  683. #ifdef CONFIG_MIZI
  684. usbc_deactivate();
  685. free_txrx_buffers();
  686. free_string_descriptors();
  687. #ifdef CONFIG_PM
  688. if (usb_char_pm_dev)
  689. pm_unregister(usb_char_pm_dev);
  690. #endif 
  691. #endif
  692. misc_deregister( &usbc_misc_device );
  693. }
  694. EXPORT_NO_SYMBOLS;
  695. module_init(usbc_init);
  696. module_exit(usbc_exit);
  697. // end: usb-char.c