免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2776 | 回复: 1
打印 上一主题 下一主题

linux USB虚拟串口驱动在内核3.1以下版本正常,3.9版本使用崩溃 [复制链接]

论坛徽章:
1
程序设计版块每日发帖之星
日期:2015-11-28 06:20:00
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2015-11-25 09:27 |只看该作者 |倒序浏览
本帖最后由 hue2550 于 2015-11-25 09:27 编辑

最近有个项目的目标板提供USB接口,主机这边通过驱动模块将USB虚拟成了一个串口,在内核3.1以下版本可正常使用,在内核3.9及以上版本使用可以加载成功,但是一旦对ttyVCOM进行读写操作时就系统崩溃了。驱动模块及错误指示如下,求大神指点。
在3.9内核里面tty_io.c中执行tty_init_dev()操作是比之前的3.1版本多出了一个tty->port的操作,请问这个tty->port该在哪里初始化?
  1. /*
  2. * Linux Virtual COM Port Driver for XinCOMM
  3. */

  4. #include <linux/kernel.h>
  5. #include <linux/errno.h>
  6. #include <linux/init.h>
  7. #include <linux/module.h>
  8. #include <linux/usb.h>
  9. #include <linux/mutex.h>
  10. #include <linux/spinlock.h>
  11. #include <linux/slab.h>
  12. #include <linux/wait.h>
  13. #include <linux/tty.h>
  14. #include <linux/tty_driver.h>
  15. #include <linux/tty_flip.h>
  16. #include <linux/serial.h>
  17. #include <asm/uaccess.h>
  18. #include <asm/byteorder.h>
  19. #include <asm/unaligned.h>



  20. #define VID 0x055f
  21. #define PID 0x017B

  22. //#define VID 0x046D
  23. //#define PID 0x0A0C

  24. #define DRIVER_VERSION "v1.0"
  25. #define DRIVER_AUTHOR "Zhang"
  26. #define DRIVER_DESC "Linux Virtual COM Driver For XinComm"

  27. /* Module information */
  28. MODULE_AUTHOR( DRIVER_AUTHOR );
  29. MODULE_DESCRIPTION( DRIVER_DESC );
  30. MODULE_LICENSE("GPL");

  31. #define XIN_MAX_SUPPORTED_DEVICES 10

  32. #define XIN_HID_INTERFACE_NUMBER 1
  33. #define XIN_HID_EP_NUMBERS 1

  34. #define XIN_TTY_MAJOR                240
  35. #define XIN_TTY_MINORS                2
  36. #define XIN_BUFFER_SIZE    2048

  37. #define HID_REQ_GET_REPORT                0x01
  38. #define HID_REQ_SET_REPORT                0x09

  39. #define OUTPUT_REPORT 0x02
  40. #define HID_INTERFACE_NUMBER 0x01

  41. /* Our fake UART values */
  42. #define MCR_DTR                0x01
  43. #define MCR_RTS                0x02
  44. #define MCR_LOOP        0x04
  45. #define MSR_CTS                0x08
  46. #define MSR_CD                0x10
  47. #define MSR_RI                0x20
  48. #define MSR_DSR                0x40

  49. typedef unsigned short USHORT;
  50. typedef unsigned char UCHAR;
  51. typedef unsigned int UINT;

  52. typedef struct __USB_HDR
  53. {
  54.         USHORT magicNumber; //0x55AA
  55.         USHORT length;
  56.         USHORT m_type: 4;
  57.         USHORT sub_type: 12;
  58.         UCHAR inOutFlag; // 0: read; 1: write
  59.         UCHAR reserved;
  60. }__attribute__((__packed__)) USB_HDR; // pay attention to ALIGNMENT

  61. #define MAX_BUFFER_SIZE 2048
  62. #define DATA_BUFFER_SIZE (MAX_BUFFER_SIZE - sizeof(USB_HDR))
  63. #define MAX_REAL_DATA_SIZE DATA_BUFFER_SIZE

  64. #define WRITE_PACKET_SIZE 60
  65. #define READ_PACKET_SIZE (512 - 4)

  66. //#define WRITE_PACKET_SIZE 60
  67. //#define READ_PACKET_SIZE (2)

  68. // for main type
  69. #define MAIN_TYPE_IP 0
  70. #define MAIN_TYPE_DEBUG 1

  71. // for sub type
  72. #define SUB_TYPE_IP        0
  73. #define SUB_TYPE_MLOG      1
  74. #define SUB_TYPE_Trace     2
  75. #define SUB_TYPE_AtCommand 3
  76. #define SUB_TYPE_ROM_UPDATE (256)

  77. #define SUB_TYPE_INVALID   0xFF

  78. // for in out flag
  79. #define DIRECTION_READ  0
  80. #define DIRECTION_WRITE 1

  81. // for magic number
  82. #define MAGIC_NUMBER 0x55AA



  83. typedef struct __USB_BUF
  84. {
  85.         USB_HDR Hdr;
  86.         UCHAR Buffer[DATA_BUFFER_SIZE];
  87. } __attribute__((__packed__)) USB_BUF;  // pay attention to ALIGNMENT


  88. struct xin_serial {
  89.         struct tty_struct        *tty;                /* pointer to the tty for this device */
  90.         int                        open_count;        /* number of times this port has been opened */

  91.         /* for tiocmget and tiocmset functions */
  92.         int                        msr;                /* MSR shadow */
  93.         int                        mcr;                /* MCR shadow */       

  94.         void*                   xinhid;
  95. };

  96. struct xin_hid {
  97.         struct usb_device *usbdev;

  98.         // interrupt in xfer
  99.         struct urb *irq;
  100.         char * irq_buf;
  101.         dma_addr_t irq_dma;

  102.         // buffer for read hid data
  103.         USB_BUF read_buffer;
  104.         int read_buffer_total_length;
  105.         int read_buffer_index;

  106.         // buffer for write hid data
  107.         USB_BUF write_buffer;
  108.         char* send_buffer;

  109.         // mutex for this HID device
  110.         spinlock_t hid_lock;

  111.         // info for serial
  112.         struct xin_serial *xin_table[XIN_TTY_MINORS];        /* initially all NULL */       
  113.         int hid_index; // the index for this HID device

  114.         // info about USB Port where this device is connected to
  115.         int xin_minor_index; // ((busnum * 1000) + (level * 100) + (portnum * 10))
  116.         int busnum;
  117.         int level;
  118.         int portnum;       
  119. };

  120. static struct tty_driver *xin_tty_driver = NULL;
  121. static struct xin_hid* hid_device_table[XIN_MAX_SUPPORTED_DEVICES] = {NULL};
  122. static DEFINE_MUTEX(global_mutex);

  123. /********************
  124. ttyVCOM0: AT command
  125. ttyVCOM1:


  126. *********************/

  127. static int xin_get_subtype_by_tty(struct xin_hid* xinhid, struct xin_serial *xin)
  128. {
  129.         int i = 0;
  130.         int subtype = SUB_TYPE_INVALID;

  131.         if(xinhid == NULL)
  132.         {
  133.                 return SUB_TYPE_INVALID;
  134.         }

  135.         for(i = 0; i < XIN_TTY_MINORS; i++)
  136.         {
  137.                 if(xin == xinhid->xin_table[i])
  138.                 {
  139.                     break;
  140.                 }
  141.         }

  142.         if(i == XIN_TTY_MINORS)
  143.         {
  144.                 return SUB_TYPE_INVALID;
  145.         }

  146.         if(i == 0)
  147.         {
  148.                 subtype = SUB_TYPE_AtCommand;
  149.         }
  150.         else if(i == 1)
  151.         {
  152.                 subtype = SUB_TYPE_ROM_UPDATE;
  153.         }
  154.        

  155.         return subtype;
  156. }

  157. static struct tty_struct *xin_get_tty_by_subtype(struct xin_hid* xinhid, int subtype)
  158. {
  159.         struct tty_struct *tty = NULL;
  160.         struct xin_serial * serial = NULL;

  161.         if(xinhid == NULL)
  162.         {
  163.                 return NULL;
  164.         }

  165.         if(subtype == SUB_TYPE_AtCommand)
  166.         {
  167.                 serial = xinhid->xin_table[0];
  168.         }
  169.         else if(subtype == SUB_TYPE_ROM_UPDATE)
  170.         {
  171.                 serial = xinhid->xin_table[1];
  172.         }
  173.        
  174.         if(!serial)
  175.         {               
  176.                 //printk(KERN_ERR "[%s] destination VCOM does not exist", __FUNCTION__);
  177.                 goto exit;
  178.         }

  179.         if (!serial->open_count)
  180.         {
  181.                 printk("[%s] no destination ttyVCOM is not opened", __FUNCTION__);
  182.                 tty = NULL;
  183.                 /* port was not opened */
  184.                 goto exit;
  185.         }

  186.         tty = serial->tty;

  187. exit:
  188.         return tty;
  189. }

  190. static int xin_open(struct tty_struct *tty, struct file *file)
  191. {
  192.         struct xin_serial *xin = NULL;
  193.         int index = 0;
  194.         int ttyindex = 0;
  195.         int result = 0;
  196.         struct xin_hid * xinhid = NULL;
  197.         int hid_index = XIN_MAX_SUPPORTED_DEVICES;
  198.         int xin_minor_index = 0;
  199.         int i = 0;

  200.         /* initialize the pointer in case something fails */
  201.         tty->driver_data = NULL;

  202.         /* get the serial object associated with this tty pointer */
  203.         ttyindex = tty->index;
  204.         printk("[%s] open ttyVCOM%d", __FUNCTION__, ttyindex);

  205.         // get the hid index and serial index from the ttyindex
  206.         xin_minor_index = ttyindex / 10;
  207.         xin_minor_index = 10 * xin_minor_index;
  208.         printk("[%s] the xin minor index for this tty is: %d", __FUNCTION__, xin_minor_index);       

  209.         for(i = 0; i < XIN_MAX_SUPPORTED_DEVICES; i++)
  210.         {
  211.                 if((hid_device_table[i] != NULL) && (hid_device_table[i]->xin_minor_index == xin_minor_index))
  212.                 {
  213.                         hid_index = i;
  214.                         break;
  215.                 }
  216.         }

  217.         if(hid_index >= XIN_MAX_SUPPORTED_DEVICES)
  218.         {
  219.                 printk("[%s] open ttyVCOM%d failed because the HID device cannot be found!!!", __FUNCTION__, ttyindex);
  220.                 return -ENODEV;
  221.         }
  222.        
  223.         xinhid = hid_device_table[hid_index];
  224.         if(xinhid == NULL)
  225.         {
  226.                 printk("[%s] open ttyVCOM%d failed because the hid device is not connected!!!", __FUNCTION__, ttyindex);
  227.                 return -ENODEV;
  228.         }

  229.         index = ttyindex - xin_minor_index;
  230.         if(index >= XIN_TTY_MINORS)
  231.         {
  232.                 printk("[%s] open ttyVCOM%d failed because of incorrect index, index = %d", __FUNCTION__, ttyindex, index);
  233.                 return -ENODEV;               
  234.         }

  235.         // open the deivce
  236.         spin_lock(&xinhid->hid_lock);
  237.        
  238.         xin = xinhid->xin_table[index];
  239.         if (xin == NULL) {
  240.                 printk("[%s] the first time to open ttyVCOM%d", __FUNCTION__, ttyindex );
  241.                 /* first time accessing this device, let's create it */
  242.                 xin = kmalloc(sizeof(*xin), GFP_KERNEL);
  243.                 if (!xin)
  244.                 {
  245.                     printk("[%s] failed to allocate memory for ttyVCOM%d", __FUNCTION__ ,ttyindex);
  246.                         result = -ENOMEM;
  247.                         goto Exit;
  248.                 }

  249.                 xin->open_count = 0;
  250.                 xin->xinhid = (void*)xinhid;
  251.                 xinhid->xin_table[index] = xin;
  252.                 xin->msr = (MSR_CD | MSR_DSR | MSR_CTS);
  253.         }

  254.         /* save our structure within the tty structure */
  255.         tty->driver_data = xin;
  256.         xin->tty = tty;
  257.         ++xin->open_count;
  258.         //tty_wakeup(tty);
  259.         printk("[%s] open ttyVCOM%d OK, count = %d", __FUNCTION__, ttyindex, xin->open_count);

  260. Exit:
  261.         spin_unlock(&xinhid->hid_lock);
  262.         return result;
  263. }

  264. static void do_close(struct xin_serial *xin)
  265. {
  266.         // the lock will be used in the function who call this function
  267.         // so no any protection in this function

  268.         if (!xin->open_count) {
  269.                 /* port was never opened */
  270.                 return;
  271.         }

  272.         --xin->open_count;
  273. }

  274. static void xin_close(struct tty_struct *tty, struct file *file)
  275. {
  276.         struct xin_serial *xin = NULL;
  277.         //struct xin_hid* xinhid = NULL; // we should not handle xinhid here. Evevything will be done when disconnect!

  278.         if(tty == NULL)
  279.         {
  280.                 printk("[%s] wrong parameter because tty is NULL !!!", __FUNCTION__);
  281.                 return;
  282.         }

  283.         printk("[%s] close ttyVCOM%d", __FUNCTION__, tty->index);

  284.         xin = tty->driver_data;
  285.         if(xin == NULL)
  286.         {
  287.                 printk("[%s] tty->driver_data is NULL!!!", __FUNCTION__);
  288.                 return;
  289.         }

  290.         if (xin)
  291.         {
  292.                 do_close(xin);
  293.         }
  294. }       


  295. static int xin_write(struct tty_struct *tty,
  296.                       const unsigned char *buffer, int count)
  297. {
  298.         struct xin_serial *xin = tty->driver_data;
  299.         struct xin_hid* xinhid = NULL;
  300.         int subtype = SUB_TYPE_INVALID;
  301.         int retval = -EINVAL;
  302.         int copylength = 0;
  303.         int copy_index = 0;
  304.         char* startptr = NULL;

  305.         printk("[%s] ttyVCOM%d write %d bytes", __FUNCTION__, tty->index, count);

  306.         if (!xin)
  307.         {       
  308.                 printk("[%s] ttyVCOM%d doesnot exist", __FUNCTION__, tty->index);
  309.                 retval = -ENODEV;
  310.                 return retval;
  311.         }

  312.         if(!count)
  313.         {
  314.                 printk("[%s] data length is ZERO, so shortcut!", __FUNCTION__);
  315.                     retval = 0;
  316.                 return retval;               
  317.         }

  318.         xinhid = (struct xin_hid*)xin->xinhid;
  319.         if(xinhid == NULL)
  320.         {
  321.                 printk("[%s] xin hid device is not connected", __FUNCTION__);       
  322.                 retval = -ENODEV;
  323.                 return retval;
  324.         }

  325.         spin_lock(&xinhid->hid_lock);

  326.         if (!xin->open_count)
  327.         {
  328.                 printk("[%s] ttyVCOM%d is not opened", __FUNCTION__, tty->index);
  329.                 /* port was not opened */
  330.                 goto exit;
  331.         }

  332.         subtype = xin_get_subtype_by_tty(xinhid, xin);
  333.         if(subtype == SUB_TYPE_INVALID)
  334.         {
  335.                 printk("[%s] cannot get subtype for ttyVCOM%d", __FUNCTION__, tty->index);
  336.                 goto exit;
  337.         }
  338.        
  339.         printk("[%s] send data from ttyVCOM%d to hid device- ", __FUNCTION__, tty->index);

  340.         copylength = count > MAX_REAL_DATA_SIZE ? MAX_REAL_DATA_SIZE : count;
  341.         memset(&xinhid->write_buffer, 0, sizeof(USB_BUF));
  342.         memcpy(&xinhid->write_buffer.Buffer[0], buffer, copylength);
  343.         xinhid->write_buffer.Hdr.magicNumber = MAGIC_NUMBER;
  344.         xinhid->write_buffer.Hdr.length = sizeof(USB_HDR) + copylength;
  345.         xinhid->write_buffer.Hdr.m_type = MAIN_TYPE_DEBUG;
  346.             xinhid->write_buffer.Hdr.inOutFlag = DIRECTION_WRITE;
  347.         xinhid->write_buffer.Hdr.sub_type = subtype;

  348.         copylength = 0;
  349.         copy_index = 0;
  350.         while(1)
  351.         {
  352.                 if(xinhid->write_buffer.Hdr.length - copy_index >= WRITE_PACKET_SIZE)
  353.                 {
  354.                         copylength = WRITE_PACKET_SIZE;
  355.                 }
  356.                 else
  357.                 {
  358.                     copylength = xinhid->write_buffer.Hdr.length - copy_index;
  359.                 }
  360.                 startptr = ((char*)(&xinhid->write_buffer)) + copy_index;
  361.                 memset(xinhid->send_buffer, 0, WRITE_PACKET_SIZE);
  362.                 memcpy(xinhid->send_buffer, startptr, copylength);               
  363.             retval = usb_control_msg(xinhid->usbdev, usb_sndctrlpipe(xinhid->usbdev, 0),
  364.                                 HID_REQ_SET_REPORT,
  365.                                 USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
  366.                                 (OUTPUT_REPORT << 8) | 0,
  367.                                 HID_INTERFACE_NUMBER, xinhid->send_buffer, WRITE_PACKET_SIZE,
  368.                                 USB_CTRL_SET_TIMEOUT);
  369.                 if(retval < 0)
  370.                 {
  371.                         printk("[%s] failed to write to HID device!, result = %d\n",__FUNCTION__, retval);
  372.                         goto exit;
  373.                 }
  374.             
  375.                 if(retval < WRITE_PACKET_SIZE)
  376.                 {
  377.                     printk("[%s] failed to write to HID device!, result = %d != %d\n", __FUNCTION__, retval, copylength);
  378.                 }
  379.                 copy_index += copylength;

  380.                 if(copy_index >= xinhid->write_buffer.Hdr.length)
  381.                 {
  382.                     printk("[%s] write complete!\n", __FUNCTION__);
  383.                         break;
  384.                 }
  385.         }
  386.        
  387.         retval = count;
  388.                
  389. exit:
  390.         spin_unlock(&xinhid->hid_lock);
  391.         return retval;
  392. }

  393. static int xin_write_room(struct tty_struct *tty)
  394. {
  395.         struct xin_serial *xin = tty->driver_data;
  396.         int room = -EINVAL;
  397.         struct xin_hid *xinhid = NULL;

  398.         if (!xin)
  399.                 return -ENODEV;

  400.         xinhid = (struct xin_hid*)xin->xinhid;
  401.         if (!xinhid)
  402.                 return -ENODEV;       

  403.         spin_lock(&xinhid->hid_lock);
  404.        
  405.         if (!xin->open_count) {
  406.                 /* port was not opened */
  407.                 goto exit;
  408.         }

  409.         /* calculate how much room is left in the device */
  410.         room = XIN_BUFFER_SIZE;

  411. exit:
  412.         spin_unlock(&xinhid->hid_lock);
  413.         return room;
  414. }

  415. #define RELEVANT_IFLAG(iflag) ((iflag) & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))

  416. static void xin_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
  417. {
  418.         unsigned int cflag;

  419.         cflag = tty->termios.c_cflag;

  420.         /* check that they really want us to change something */
  421.         if (old_termios) {
  422.                 if ((cflag == old_termios->c_cflag) &&
  423.                     (RELEVANT_IFLAG(tty->termios.c_iflag) ==
  424.                      RELEVANT_IFLAG(old_termios->c_iflag))) {
  425.                         printk(" - nothing to change...\n");
  426.                         return;
  427.                 }
  428.         }

  429.         /* get the byte size */
  430.         switch (cflag & CSIZE) {
  431.                 case CS5:
  432.                         printk(" - data bits = 5\n");
  433.                         break;
  434.                 case CS6:
  435.                         printk(" - data bits = 6\n");
  436.                         break;
  437.                 case CS7:
  438.                         printk(" - data bits = 7\n");
  439.                         break;
  440.                 default:
  441.                 case CS8:
  442.                         printk(" - data bits = 8\n");
  443.                         break;
  444.         }
  445.        
  446.         /* determine the parity */
  447.         if (cflag & PARENB)
  448.                 if (cflag & PARODD)
  449.                         printk(" - parity = odd\n");
  450.                 else
  451.                         printk(" - parity = even\n");
  452.         else
  453.                 printk(" - parity = none\n");

  454.         /* figure out the stop bits requested */
  455.         if (cflag & CSTOPB)
  456.                 printk(" - stop bits = 2\n");
  457.         else
  458.                 printk(" - stop bits = 1\n");

  459.         /* figure out the hardware flow control settings */
  460.         if (cflag & CRTSCTS)
  461.                 printk(" - RTS/CTS is enabled\n");
  462.         else
  463.                 printk(" - RTS/CTS is disabled\n");
  464.        
  465.         /* determine software flow control */
  466.         /* if we are implementing XON/XOFF, set the start and
  467.          * stop character in the device */
  468.         if (I_IXOFF(tty) || I_IXON(tty)) {
  469.                 unsigned char stop_char  = STOP_CHAR(tty);
  470.                 unsigned char start_char = START_CHAR(tty);

  471.                 /* if we are implementing INBOUND XON/XOFF */
  472.                 if (I_IXOFF(tty))
  473.                         printk(" - INBOUND XON/XOFF is enabled, "
  474.                                 "XON = %2x, XOFF = %2x", start_char, stop_char);
  475.                 else
  476.                         printk(" - INBOUND XON/XOFF is disabled");

  477.                 /* if we are implementing OUTBOUND XON/XOFF */
  478.                 if (I_IXON(tty))
  479.                         printk(" - OUTBOUND XON/XOFF is enabled, "
  480.                                 "XON = %2x, XOFF = %2x", start_char, stop_char);
  481.                 else
  482.                         printk(" - OUTBOUND XON/XOFF is disabled");
  483.         }

  484.         /* get the baud rate wanted */
  485.         printk(" - baud rate = %d", tty_get_baud_rate(tty));
  486. }


  487. static int xin_tiocmget(struct tty_struct *tty)
  488. {
  489.         struct xin_serial *xin = tty->driver_data;

  490.         unsigned int result = 0;
  491.         unsigned int msr = xin->msr;
  492.         unsigned int mcr = xin->mcr;

  493.         result = ((mcr & MCR_DTR)  ? TIOCM_DTR  : 0) |        /* DTR is set */
  494.              ((mcr & MCR_RTS)  ? TIOCM_RTS  : 0) |        /* RTS is set */
  495.              ((mcr & MCR_LOOP) ? TIOCM_LOOP : 0) |        /* LOOP is set */
  496.              ((msr & MSR_CTS)  ? TIOCM_CTS  : 0) |        /* CTS is set */
  497.              ((msr & MSR_CD)   ? TIOCM_CAR  : 0) |        /* Carrier detect is set*/
  498.              ((msr & MSR_RI)   ? TIOCM_RI   : 0) |        /* Ring Indicator is set */
  499.              ((msr & MSR_DSR)  ? TIOCM_DSR  : 0);        /* DSR is set */

  500.         return result;
  501. }

  502. static int xin_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear)
  503. {
  504.         struct xin_serial *xin = tty->driver_data;
  505.         unsigned int mcr = xin->mcr;

  506.         if (set & TIOCM_RTS)
  507.                 mcr |= MCR_RTS;
  508.         if (set & TIOCM_DTR)
  509.                 mcr |= MCR_RTS;

  510.         if (clear & TIOCM_RTS)
  511.                 mcr &= ~MCR_RTS;
  512.         if (clear & TIOCM_DTR)
  513.                 mcr &= ~MCR_RTS;

  514.         /* set the new MCR value in the device */
  515.         xin->mcr = mcr;
  516.         return 0;
  517. }

  518. static int xin_hid_alloc_mem(struct usb_device *dev, struct xin_hid *xinhid)
  519. {
  520.         if (!(xinhid->irq = usb_alloc_urb(0, GFP_KERNEL)))
  521.                 return -1;

  522.         //if (!(xinhid->irq_buf = usb_buffer_alloc(dev, READ_PACKET_SIZE, GFP_ATOMIC, &xinhid->irq_dma)))
  523.         if (!(xinhid->irq_buf = usb_alloc_coherent(dev, READ_PACKET_SIZE, GFP_KERNEL, &xinhid->irq_dma)))
  524.                 return -1;

  525.         if (!(xinhid->send_buffer = kmalloc(WRITE_PACKET_SIZE, GFP_KERNEL)))
  526.                 return -1;       

  527.         return 0;
  528. }

  529. static void xin_hid_free_mem(struct usb_device *dev, struct xin_hid *xinhid)
  530. {
  531.         usb_free_urb(xinhid->irq);
  532.         //usb_free_coherent(dev, READ_PACKET_SIZE, xinhid->irq_buf, xinhid->irq_dma);
  533.         usb_free_coherent(dev, READ_PACKET_SIZE, xinhid->irq_buf, xinhid->irq_dma);
  534.         kfree(xinhid->send_buffer);
  535. }


  536. static void xin_irq(struct urb *urb)
  537. {
  538.         struct xin_hid *xinhid = urb->context;
  539.         int i;
  540.         int datalength = 0;
  541.         int copylength = 0;
  542.         char* startptr = NULL;
  543.        
  544.         struct tty_struct *tty = NULL;
  545.         int subtype = SUB_TYPE_INVALID;

  546.         if(xinhid == NULL)
  547.         {
  548.             printk("[%s] xinhid is NULL\n", __FUNCTION__);
  549.                 return;
  550.         }

  551.         switch (urb->status) {
  552.         case 0:                        /* success */
  553.                 break;
  554.         case -ECONNRESET:        /* unlink */
  555.         case -ENOENT:
  556.         case -ESHUTDOWN:
  557.                 printk("[%s] irq complete error in place 1, status: %d\n", __FUNCTION__, urb->status);
  558.                 return;
  559.         /* -EPIPE:  should clear the halt */
  560.         default:                /* error */
  561.                 printk("[%s] irq complete error in place 2, status: %d\n", __FUNCTION__, urb->status);
  562.                 goto resubmit;
  563.         }

  564.         //
  565.         datalength = urb->actual_length;
  566.         //printk(KERN_ERR "[%s] get %d bytes from xin100 hid device\n", __FUNCTION__, datalength);
  567.         if(xinhid->read_buffer_total_length == 0)
  568.         {
  569.                 copylength = datalength;
  570.         }
  571.         else if( datalength + xinhid->read_buffer_index >= xinhid->read_buffer_total_length)
  572.         {
  573.                 copylength = xinhid->read_buffer_total_length - xinhid->read_buffer_index;
  574.         }
  575.         else
  576.         {
  577.                 copylength = datalength;
  578.         }

  579.         startptr = ((char*)&xinhid->read_buffer) + xinhid->read_buffer_index;
  580.         memcpy(startptr, urb->transfer_buffer, copylength);
  581.         if(xinhid->read_buffer_total_length == 0)
  582.         {
  583.             xinhid->read_buffer_total_length = xinhid->read_buffer.Hdr.length;
  584.                 if(xinhid->read_buffer_total_length > MAX_BUFFER_SIZE)
  585.                 {
  586.                         //device should not send much messages but AT responses.
  587.                         /*printk(KERN_ERR "[%s] wrong length %d in header (should <= 2048 )\n", __FUNCTION__, xinhid->read_buffer_total_length);*/
  588.                         xinhid->read_buffer_total_length = MAX_BUFFER_SIZE;
  589.                 }
  590.         }
  591.         xinhid->read_buffer_index += copylength;

  592.         if(xinhid->read_buffer_index >= xinhid->read_buffer_total_length)
  593.         {
  594.             // get the whole data
  595.             //printk(KERN_ERR "[%s] get whole %d bytes from xin100 hid device\n", __FUNCTION__, xinhid->read_buffer_total_length);

  596.                 // send the data to tty com port
  597.         if(xinhid->read_buffer.Hdr.magicNumber != MAGIC_NUMBER)
  598.         {
  599.                         printk("[%s] wrong magic number: 0x%04x (should 0x55AA)\n", __FUNCTION__, xinhid->read_buffer.Hdr.magicNumber);
  600.                 goto cleanbuffer;
  601.         }

  602.                 if(xinhid->read_buffer.Hdr.m_type != MAIN_TYPE_DEBUG)
  603.                 {
  604.                         printk("[%s] wrong major type\n", __FUNCTION__);
  605.                         goto cleanbuffer;
  606.                 }

  607.                 subtype = xinhid->read_buffer.Hdr.sub_type;
  608.                 tty = xin_get_tty_by_subtype(xinhid, subtype);
  609.                 if(tty != NULL)
  610.                 {
  611.                         tty_insert_flip_string(tty->port, &xinhid->read_buffer.Buffer[0], xinhid->read_buffer_total_length - sizeof(USB_HDR));
  612.                         tty_flip_buffer_push(tty->port);
  613.                 }
  614.                 else
  615.                 {
  616.                         //printk(KERN_ERR "[%s] no available tty for the received data\n", __FUNCTION__);
  617.                         goto cleanbuffer;
  618.                 }
  619.                
  620. cleanbuffer:
  621.                 memset(&xinhid->read_buffer, 0, sizeof(USB_BUF));
  622.                 xinhid->read_buffer_index = 0;
  623.                 xinhid->read_buffer_total_length = 0;               
  624.         }

  625. resubmit:
  626.         i = usb_submit_urb (urb, GFP_ATOMIC);
  627.         if (i)
  628.                 printk("[%s] can't resubmit intr, status %d", __FUNCTION__, i);
  629. }


  630. static int xin_probe(struct usb_interface *iface,
  631.                          const struct usb_device_id *id)
  632. {
  633.         struct usb_device *dev = NULL;
  634.         struct usb_host_interface *interface = NULL;
  635.         struct usb_endpoint_descriptor *endpoint = NULL;
  636.         struct xin_hid *xinhid = NULL;
  637.         int pipe = 0, maxp = 0;
  638.         int error = -ENOMEM;
  639.         int i = 0;
  640.         int hid_index = XIN_MAX_SUPPORTED_DEVICES;

  641.         printk("[%s] xin_probe start...\n", __FUNCTION__);

  642.         if(iface == NULL)
  643.         {
  644.                 printk("[%s] iface is NULL\n", __FUNCTION__);
  645.                 return -ENODEV;
  646.         }

  647.         dev = interface_to_usbdev(iface);

  648.         interface = iface->cur_altsetting;
  649.         if ((interface->desc.bInterfaceNumber != XIN_HID_INTERFACE_NUMBER) || (interface->desc.bNumEndpoints != XIN_HID_EP_NUMBERS))
  650.         {
  651.                 printk("[%s] Not HID Interface, because bInterfaceNumber or bNumEndpoints are wrong!\n", __FUNCTION__);
  652.                 return -ENODEV;
  653.         }

  654.         endpoint = &interface->endpoint[0].desc;
  655.         if (!usb_endpoint_is_int_in(endpoint))
  656.         {
  657.                 printk("[%s] endpoint type for HID interface is wrong! (should be interrupt in)!\n", __FUNCTION__);
  658.                 return -ENODEV;
  659.         }

  660.         pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
  661.         maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));

  662.         xinhid = kzalloc(sizeof(struct xin_hid), GFP_KERNEL);
  663.         if (!xinhid)
  664.         {
  665.                 printk("[%s] failed to allocate memory for struct xinhid!\n", __FUNCTION__);
  666.                 goto fail1;
  667.         }

  668.         if (xin_hid_alloc_mem(dev, xinhid))
  669.         {
  670.                 printk("[%s] failed to allocate memory for urb and buffer!\n", __FUNCTION__);
  671.                 goto fail2;
  672.         }
  673.        
  674.         spin_lock_init(&xinhid->hid_lock);

  675.         xinhid->read_buffer_total_length = 0;
  676.         xinhid->read_buffer_index = 0;
  677.        
  678.         xinhid->usbdev = dev;

  679.         xinhid->busnum = dev->bus->busnum;
  680.         xinhid->level = dev->level;
  681.         xinhid->portnum = dev->portnum;

  682.         xinhid->xin_minor_index = (xinhid->busnum * 1000) + (xinhid->level * 100) + (xinhid->portnum * 10);

  683.         printk("[%s] xin_minor_index: %d, busnum: %d, level: %d, portnum: %d", __FUNCTION__, xinhid->xin_minor_index, xinhid->busnum, xinhid->level, xinhid->portnum);

  684.         // find the available serial index for this hid device
  685.         mutex_lock(&global_mutex);
  686.         for(i = 0; i < XIN_MAX_SUPPORTED_DEVICES; i++)
  687.         {
  688.                 if(hid_device_table[i] == NULL)
  689.                 {
  690.                         hid_index = i;                       
  691.                         break;
  692.                 }
  693.         }

  694.         if(hid_index >= XIN_MAX_SUPPORTED_DEVICES)
  695.         {
  696.                 printk("[%s] too many devices are inserted!!!", __FUNCTION__);
  697.                 mutex_unlock(&global_mutex);
  698.                 goto fail2;
  699.         }

  700.         xinhid->hid_index = hid_index;
  701.         hid_device_table[hid_index] = xinhid;

  702.         for (i = 0; i < XIN_TTY_MINORS; i++)
  703.         {
  704.                 printk("[%s] register ttyVCOM%d\n", __FUNCTION__, xinhid->xin_minor_index + i);
  705.                 tty_register_device(xin_tty_driver, xinhid->xin_minor_index + i, NULL);
  706.         }

  707.                mutex_unlock(&global_mutex);

  708.         // init the interrupt in urb and submit the first urb

  709.         usb_fill_int_urb(xinhid->irq, dev, pipe,
  710.                          xinhid->irq_buf, (maxp > 1024 ? 1024 : maxp),
  711.                          xin_irq, xinhid, endpoint->bInterval);
  712.         xinhid->irq->transfer_dma = xinhid->irq_dma;
  713.         xinhid->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;

  714.         if (usb_submit_urb(xinhid->irq, GFP_ATOMIC))
  715.         {
  716.                 error = -EIO;               
  717.                 printk("[%s] failed to submit interrupt in urb!\n", __FUNCTION__);
  718.                 goto fail3;
  719.         }

  720.         usb_set_intfdata(iface, xinhid);

  721.         printk("[%s] xin_probe success!\n", __FUNCTION__);
  722.        
  723.         return 0;

  724. fail3:
  725.         mutex_lock(&global_mutex);
  726.         for (i = 0; i < XIN_TTY_MINORS; ++i)
  727.         {
  728.                 tty_unregister_device(xin_tty_driver, xinhid->xin_minor_index + i);
  729.         }       
  730.         hid_device_table[xinhid->hid_index] = NULL;
  731.         mutex_unlock(&global_mutex);       

  732. fail2:       
  733.         xin_hid_free_mem(dev, xinhid);
  734. fail1:       
  735.         kfree(xinhid);
  736.         return error;
  737. }

  738. static void xin_disconnect(struct usb_interface *intf)
  739. {
  740.         struct xin_hid *xinhid = usb_get_intfdata (intf);
  741.         int i = 0;
  742.         struct xin_serial *xin = NULL;
  743.         int hid_index = 0;

  744.         printk("[%s] xin_disconnect\n", __FUNCTION__);

  745.         if(xinhid == NULL)
  746.         {
  747.                 printk("[%s] no available hid device in disconnect!!!\n", __FUNCTION__);
  748.                 return;
  749.         }

  750.         hid_index = xinhid->hid_index;

  751.         printk("[%s] before unregister VCOM device\n", __FUNCTION__);

  752.         mutex_lock(&global_mutex);
  753.         for (i = 0; i < XIN_TTY_MINORS; ++i)
  754.         {
  755.                 printk("[%s] unregister ttyVCOM%d device\n", __FUNCTION__, xinhid->xin_minor_index + i);
  756.                 tty_unregister_device(xin_tty_driver, xinhid->xin_minor_index + i);
  757.         }
  758.         hid_device_table[hid_index] = NULL;
  759.         mutex_unlock(&global_mutex);

  760.         printk("[%s] shut down hid device\n", __FUNCTION__);

  761.         spin_lock(&xinhid->hid_lock);

  762.         /* shut down all serial device and free the memory */
  763.         for (i = 0; i < XIN_TTY_MINORS; ++i) {
  764.                 xin = xinhid->xin_table[i];
  765.                 if (xin) {
  766.                         /* close the port */
  767.                         while (xin->open_count)
  768.                                 do_close(xin);

  769.                         /* free the memory */
  770.                         kfree(xin);
  771.                         xinhid->xin_table[i] = NULL;
  772.                 }
  773.         }       

  774.         usb_set_intfdata(intf, NULL);
  775.         usb_kill_urb(xinhid->irq);
  776.         xin_hid_free_mem(interface_to_usbdev(intf), xinhid);

  777.         spin_unlock(&xinhid->hid_lock);

  778.         kfree(xinhid);

  779.         xinhid = NULL;
  780.        
  781.         printk(KERN_ERR "[%s] xin_disconnect success\n", __FUNCTION__);
  782. }

  783. static struct tty_operations serial_ops = {
  784.         .open = xin_open,
  785.         .close = xin_close,
  786.         .write = xin_write,
  787.         .write_room = xin_write_room,
  788.         .set_termios = xin_set_termios,
  789.         .tiocmget =        xin_tiocmget,       
  790.         .tiocmset =        xin_tiocmset,
  791. };

  792. static const struct usb_device_id        products [] = {

  793. #define        XIN100_HID_INTERFACE \
  794.         .bInterfaceClass        = 0xff, \
  795.         .bInterfaceSubClass        = 0xff, \
  796.         .bInterfaceProtocol        = 0xff

  797. /*
  798. * Xin100 USB HID uses just one USB interface.
  799. */
  800. {
  801.         .match_flags        =   USB_DEVICE_ID_MATCH_INT_INFO
  802.                           | USB_DEVICE_ID_MATCH_DEVICE,
  803.         .idVendor                = VID,
  804.         .idProduct                = PID,
  805.         XIN100_HID_INTERFACE
  806. },{ },                // END
  807. };
  808. MODULE_DEVICE_TABLE(usb, products);

  809. static struct usb_driver xin_hid_driver = {
  810.         .name =                "ttyxin",
  811.         .id_table =        products,
  812.         .probe =        xin_probe,
  813.         .disconnect =        xin_disconnect,
  814. };
  815. static int __init xin_init(void)
  816. {
  817.         int retval;
  818.         int i = 0;
  819.         int max_tty_index = 0;

  820.         printk("[%s] init ttyxin driver", __FUNCTION__);

  821.         for(i = 0; i < XIN_MAX_SUPPORTED_DEVICES; i++)
  822.         {
  823.                 hid_device_table[i] = NULL;
  824.         }

  825.         /* allocate the tty driver */
  826.         max_tty_index = 0xFFFF;
  827.         xin_tty_driver = alloc_tty_driver(max_tty_index);
  828.         if (!xin_tty_driver)
  829.         {
  830.             printk("[%s] failed to alloc tty driver", __FUNCTION__);
  831.                 return -ENOMEM;
  832.         }

  833.         //printk(KERN_ERR "[%s] xin_tty_driver is 0x%08x", __FUNCTION__, (unsigned int)xin_tty_driver);

  834.         /* initialize the tty driver */
  835.         xin_tty_driver->owner = THIS_MODULE;
  836.         xin_tty_driver->driver_name = "ttyxin";
  837.         xin_tty_driver->name = "ttyVCOM";
  838.         xin_tty_driver->major = XIN_TTY_MAJOR,
  839.     xin_tty_driver->minor_start = 0,
  840.         xin_tty_driver->type = TTY_DRIVER_TYPE_SERIAL,
  841.         xin_tty_driver->subtype = SERIAL_TYPE_NORMAL,
  842.         xin_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV,
  843.         xin_tty_driver->init_termios = tty_std_termios;
  844.         xin_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
  845.         xin_tty_driver->init_termios.c_lflag &= ~(ECHO|ECHONL|ICANON|ECHOE);
  846.         tty_set_operations(xin_tty_driver, &serial_ops);

  847.         /* register the tty driver */
  848.         retval = tty_register_driver(xin_tty_driver);
  849.         if (retval) {
  850.                 printk("[%s] failed to register xin tty driver", __FUNCTION__);
  851.                 put_tty_driver(xin_tty_driver);
  852.                 return retval;
  853.         }

  854.         retval = usb_register(&xin_hid_driver);
  855.         if(retval)
  856.         {
  857.                 printk("[%s] failed to register xin hid driver", __FUNCTION__);
  858.                 put_tty_driver(xin_tty_driver);
  859.                 tty_unregister_driver(xin_tty_driver);
  860.                 return retval;
  861.         }

  862.         printk(KERN_ERR DRIVER_DESC " " DRIVER_VERSION);
  863.         return retval;
  864. }

  865. static void __exit xin_exit(void)
  866. {
  867.         printk("[%s] uninit xin com driver", __FUNCTION__);

  868.         usb_deregister(&xin_hid_driver);
  869.         tty_unregister_driver(xin_tty_driver);
  870.         xin_tty_driver = NULL;

  871.         printk("[%s] uninit xin com driver success", __FUNCTION__);

  872. }

  873. module_init(xin_init);
  874. module_exit(xin_exit);
复制代码

论坛徽章:
1
程序设计版块每日发帖之星
日期:2015-11-28 06:20:00
2 [报告]
发表于 2015-11-25 16:34 |只看该作者
问题以解决,在probe函数中增加tty port与tty device的对应即可
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP