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