Contiki-NG
Loading...
Searching...
No Matches
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
15static uint8_t usb_ctrl_data_buffer[32];
16
17static struct usb_cdc_line_coding usb_line_coding = { 9600, 0x00, 0x00, 0x08 }; // 9600 baud, 8N1
18static uint8_t line_state;
19static uint8_t events;
20static struct process *cdc_event_process = NULL;
21
22static void
23notify_user(uint8_t e)
24{
25 events |= e;
26 if(cdc_event_process) {
27 process_poll(cdc_event_process);
28 }
29}
30
31static void
32encapsulated_command(uint8_t *data, unsigned int length)
33{
34 PRINTF("Got CDC command: length %d\n", length);
35 usb_send_ctrl_status();
36}
37static void
38set_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
63static unsigned int
64handle_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
117static const struct USBRequestHandler cdc_acm_request_handler = {
118 0x21, 0x7f,
119 0x00, 0x00,
120 handle_cdc_acm_requests
121};
122
123static struct USBRequestHandlerHook cdc_acm_request_hook = {
124 NULL,
125 &cdc_acm_request_handler
126};
127
128void
129usb_cdc_acm_setup()
130{
131 usb_register_request_handler(&cdc_acm_request_hook);
132}
133
134uint8_t
135usb_cdc_acm_get_events(void)
136{
137 uint8_t r = events;
138 events = 0;
139 return r;
140}
141
142uint8_t
143usb_cdc_acm_get_line_state(void)
144{
145 return line_state;
146}
147
148const struct usb_cdc_line_coding *
149usb_cdc_acm_get_line_coding(void)
150{
151 return &usb_line_coding;
152}
153
154void
155usb_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:375