Contiki-NG
cdc-acm.c
1 #include "cdc-acm.h"
2 #include "cdc.h"
3 #include "usb-api.h"
4 #include "usb-core.h"
5 
6 #include <stdio.h>
7 #include <string.h>
8 
9 #ifdef DEBUG
10 #define PRINTF(...) printf(__VA_ARGS__)
11 #else
12 #define PRINTF(...)
13 #endif
14 
15 static uint8_t usb_ctrl_data_buffer[32];
16 
17 static struct usb_cdc_line_coding usb_line_coding = { 9600, 0x00, 0x00, 0x08 }; // 9600 baud, 8N1
18 static uint8_t line_state;
19 static uint8_t events;
20 static struct process *cdc_event_process = NULL;
21 
22 static void
23 notify_user(uint8_t e)
24 {
25  events |= e;
26  if(cdc_event_process) {
27  process_poll(cdc_event_process);
28  }
29 }
30 
31 static void
32 encapsulated_command(uint8_t *data, unsigned int length)
33 {
34  PRINTF("Got CDC command: length %d\n", length);
35  usb_send_ctrl_status();
36 }
37 static void
38 set_line_encoding(uint8_t *data, unsigned int length)
39 {
40  if(length == 7) {
41 #ifdef DEBUG
42  static const char parity_char[] = { 'N', 'O', 'E', 'M', 'S' };
43  static const char *stop_bits_str[] = { "1", "1.5", "2" };
44  const struct usb_cdc_line_coding *coding =
45  (const struct usb_cdc_line_coding *)usb_ctrl_data_buffer;
46  char parity = ((coding->bParityType > 4)
47  ? '?' : parity_char[coding->bParityType]);
48 
49  const char *stop_bits = ((coding->bCharFormat > 2)
50  ? "?" : stop_bits_str[coding->bCharFormat]);
51 
52  PRINTF("Got CDC line coding: %ld/%d/%c/%s\n",
53  coding->dwDTERate, coding->bDataBits, parity, stop_bits);
54 #endif
55  memcpy(&usb_line_coding, data, sizeof(usb_line_coding));
56  notify_user(USB_CDC_ACM_LINE_CODING);
57  usb_send_ctrl_status();
58  } else {
59  usb_error_stall();
60  }
61 }
62 
63 static unsigned int
64 handle_cdc_acm_requests()
65 {
66  PRINTF("CDC request %02x %02x\n", usb_setup_buffer.bmRequestType,
67  usb_setup_buffer.bRequest);
68  switch (usb_setup_buffer.bmRequestType) {
69  case 0x21: /* CDC interface OUT requests */
70  /* Check if it's the right interface */
71  if(usb_setup_buffer.wIndex != 0)
72  return 0;
73  switch (usb_setup_buffer.bRequest) {
74  case SET_CONTROL_LINE_STATE:
75  line_state = usb_setup_buffer.wValue;
76  notify_user(USB_CDC_ACM_LINE_STATE);
77  usb_send_ctrl_status();
78  return 1;
79 
80  case SEND_ENCAPSULATED_COMMAND:
81  {
82  unsigned int len = usb_setup_buffer.wLength;
83  if(len > sizeof(usb_ctrl_data_buffer))
84  len = sizeof(usb_ctrl_data_buffer);
85  usb_get_ctrl_data(usb_ctrl_data_buffer, len, encapsulated_command);
86  }
87 
88  return 1;
89 
90 
91  case SET_LINE_CODING:
92  {
93  unsigned int len = usb_setup_buffer.wLength;
94  if(len > sizeof(usb_ctrl_data_buffer))
95  len = sizeof(usb_ctrl_data_buffer);
96  usb_get_ctrl_data(usb_ctrl_data_buffer, len, set_line_encoding);
97  }
98  return 1;
99  }
100  break;
101  case 0xa1: /* CDC interface IN requests */
102  if(usb_setup_buffer.wIndex != 0)
103  return 0;
104  switch (usb_setup_buffer.bRequest) {
105  case GET_ENCAPSULATED_RESPONSE:
106  PRINTF("CDC response");
107  usb_send_ctrl_status();
108  return 1;
109  case GET_LINE_CODING:
110  usb_send_ctrl_response((uint8_t *) & usb_line_coding, 7);
111  return 1;
112  }
113  }
114  return 0;
115 }
116 
117 static const struct USBRequestHandler cdc_acm_request_handler = {
118  0x21, 0x7f,
119  0x00, 0x00,
120  handle_cdc_acm_requests
121 };
122 
123 static struct USBRequestHandlerHook cdc_acm_request_hook = {
124  NULL,
125  &cdc_acm_request_handler
126 };
127 
128 void
129 usb_cdc_acm_setup()
130 {
131  usb_register_request_handler(&cdc_acm_request_hook);
132 }
133 
134 uint8_t
135 usb_cdc_acm_get_events(void)
136 {
137  uint8_t r = events;
138  events = 0;
139  return r;
140 }
141 
142 uint8_t
143 usb_cdc_acm_get_line_state(void)
144 {
145  return line_state;
146 }
147 
148 const struct usb_cdc_line_coding *
149 usb_cdc_acm_get_line_coding(void)
150 {
151  return &usb_line_coding;
152 }
153 
154 void
155 usb_cdc_acm_set_event_process(struct process *p)
156 {
157  cdc_event_process = p;
158 }
void process_poll(struct process *p)
Request a process to be polled.
Definition: process.c:371