cdc_acm.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. /*
  2. * cdc_acm.c
  3. *
  4. * USB CDC ACM handling (Communications Device Class, Abstract Control Model).
  5. *
  6. * Written & released by Keir Fraser <keir.xen@gmail.com>
  7. *
  8. * This is free and unencumbered software released into the public domain.
  9. * See the file COPYING for more details, or visit <http://unlicense.org>.
  10. */
  11. #define TRACE 1
  12. /* CDC Communications Class requests */
  13. #define CDC_SET_LINE_CODING 0x20
  14. #define CDC_GET_LINE_CODING 0x21
  15. #define CDC_SET_CONTROL_LINE_STATE 0x22
  16. #define CDC_SEND_BREAK 0x23
  17. static struct packed line_coding {
  18. uint32_t baud;
  19. uint8_t nr_stop;
  20. uint8_t parity;
  21. uint8_t nr_data;
  22. } line_coding = {
  23. .baud = 9600,
  24. .nr_stop = 0,
  25. .parity = 0,
  26. .nr_data = 8 };
  27. #if TRACE
  28. #define TRC printk
  29. #else
  30. static inline void TRC(const char *format, ...) { }
  31. #endif
  32. static void dump_line_coding(const struct line_coding *lc)
  33. {
  34. int parity = (lc->parity > 4) ? 5 : lc->parity;
  35. TRC("%u,%u%c%s\n", lc->baud, lc->nr_data,
  36. "noems?"[parity],
  37. (lc->nr_stop == 0) ? "1"
  38. : (lc->nr_stop == 1) ? "1.5"
  39. : (lc->nr_stop == 2) ? "2" : "X");
  40. }
  41. bool_t cdc_acm_handle_class_request(void)
  42. {
  43. struct usb_device_request *req = &ep0.req;
  44. bool_t handled = TRUE;
  45. switch (req->bRequest) {
  46. case CDC_SET_LINE_CODING: {
  47. struct line_coding *lc = (struct line_coding *)ep0.data;
  48. TRC("SET_LINE_CODING: ");
  49. dump_line_coding(lc);
  50. if (line_coding.baud != lc->baud) {
  51. switch (lc->baud) {
  52. case BAUD_CLEAR_COMMS:
  53. usb_cdc_acm_ops.configure();
  54. printk("Comms Line Cleared\n");
  55. break;
  56. }
  57. }
  58. line_coding = *lc;
  59. break;
  60. }
  61. case CDC_GET_LINE_CODING: {
  62. struct line_coding *lc = (struct line_coding *)ep0.data;
  63. TRC("GET_LINE_CODING: ");
  64. *lc = line_coding;
  65. dump_line_coding(lc);
  66. ep0.data_len = sizeof(*lc);
  67. break;
  68. }
  69. case CDC_SET_CONTROL_LINE_STATE:
  70. /* wValue = DTR/RTS. We ignore them and return success. */
  71. break;
  72. case CDC_SEND_BREAK:
  73. /* wValue = #millisecs. We ignore it and return success. */
  74. TRC("BREAK\n");
  75. break;
  76. default:
  77. WARN("[Class-specific: %02x]\n", req->bRequest);
  78. handled = FALSE;
  79. break;
  80. }
  81. return handled;
  82. }
  83. bool_t cdc_acm_set_configuration(void)
  84. {
  85. uint8_t bulk_type = EPT_DBLBUF;
  86. #ifdef BOOTLOADER
  87. /* We don't bother with the complicated double-buffered endpoints. The
  88. * regular bulk endpoints are fast enough and possibly more reliable. */
  89. bulk_type = EPT_BULK;
  90. #endif
  91. gw_info.usb_speed = usb_is_highspeed() ? 1 : 0;
  92. /* Notification Element (D->H) */
  93. usb_configure_ep(0x81, EPT_INTERRUPT, 0);
  94. /* Bulk Pipe (H->D) */
  95. usb_configure_ep(0x02, bulk_type, usb_bulk_mps);
  96. /* Bulk Pipe (D->H) */
  97. usb_configure_ep(0x83, bulk_type, usb_bulk_mps);
  98. usb_cdc_acm_ops.configure();
  99. return TRUE;
  100. }
  101. /*
  102. * Local variables:
  103. * mode: C
  104. * c-file-style: "Linux"
  105. * c-basic-offset: 4
  106. * tab-width: 4
  107. * indent-tabs-mode: nil
  108. * End:
  109. */