cdc_acm.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  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. line_coding = *lc;
  51. break;
  52. }
  53. case CDC_GET_LINE_CODING: {
  54. struct line_coding *lc = (struct line_coding *)ep0.data;
  55. TRC("GET_LINE_CODING: ");
  56. *lc = line_coding;
  57. dump_line_coding(lc);
  58. ep0.data_len = sizeof(*lc);
  59. break;
  60. }
  61. case CDC_SET_CONTROL_LINE_STATE:
  62. /* wValue = DTR/RTS. We ignore them and return success. */
  63. break;
  64. case CDC_SEND_BREAK:
  65. /* wValue = #millisecs. We ignore it and return success. */
  66. TRC("BREAK\n");
  67. floppy_reset();
  68. floppy_configured();
  69. break;
  70. default:
  71. WARN("[Class-specific: %02x]\n", req->bRequest);
  72. handled = FALSE;
  73. break;
  74. }
  75. return handled;
  76. }
  77. bool_t cdc_acm_set_configuration(void)
  78. {
  79. /* Set up endpoints. */
  80. usb_configure_ep(0x81, 0, 0); /* Notification Element (D->H) */
  81. usb_configure_ep(0x02, 0, USB_FS_MPS); /* Bulk Pipe (H->D) */
  82. usb_configure_ep(0x82, 0, USB_FS_MPS); /* Bulk Pipe (D->H) */
  83. floppy_configured();
  84. return TRUE;
  85. }
  86. /*
  87. * Local variables:
  88. * mode: C
  89. * c-file-style: "Linux"
  90. * c-basic-offset: 4
  91. * tab-width: 4
  92. * indent-tabs-mode: nil
  93. * End:
  94. */