blob: fb57c2f3ca36d727decc13dc71908c2f2fdb78d5 [file] [log] [blame]
Kévin Redon69b92d92019-01-24 16:39:20 +01001/*
2 * Code generated from Atmel Start.
3 *
4 * This file will be overwritten when reconfiguring your Atmel Start project.
5 * Please copy examples or other code you want to keep to a separate file or main.c
6 * to avoid loosing it when reconfiguring.
7 */
8#include "atmel_start.h"
9#include "usb_start.h"
10
Kévin Redon69b92d92019-01-24 16:39:20 +010011#define CDCD_ECHO_BUF_SIZ CONF_USB_CDCD_ACM_DATA_BULKIN_MAXPKSZ
Kévin Redon69b92d92019-01-24 16:39:20 +010012
13/** Buffers to receive and echo the communication bytes. */
14static uint32_t usbd_cdc_buffer[CDCD_ECHO_BUF_SIZ / 4];
15
16/** Ctrl endpoint buffer */
17static uint8_t ctrl_buffer[64];
18
19/**
20 * \brief Callback invoked when bulk OUT data received
21 */
22static bool usb_device_cb_bulk_out(const uint8_t ep, const enum usb_xfer_code rc, const uint32_t count)
23{
24 cdcdf_acm_write((uint8_t *)usbd_cdc_buffer, count);
25
26 /* No error. */
27 return false;
28}
29
30/**
31 * \brief Callback invoked when bulk IN data received
32 */
33static bool usb_device_cb_bulk_in(const uint8_t ep, const enum usb_xfer_code rc, const uint32_t count)
34{
35 /* Echo data. */
36 cdcdf_acm_read((uint8_t *)usbd_cdc_buffer, sizeof(usbd_cdc_buffer));
37
38 /* No error. */
39 return false;
40}
41
42/**
43 * \brief Callback invoked when Line State Change
44 */
45static bool usb_device_cb_state_c(usb_cdc_control_signal_t state)
46{
47 if (state.rs232.DTR) {
48 /* Callbacks must be registered after endpoint allocation */
49 cdcdf_acm_register_callback(CDCDF_ACM_CB_READ, (FUNC_PTR)usb_device_cb_bulk_out);
50 cdcdf_acm_register_callback(CDCDF_ACM_CB_WRITE, (FUNC_PTR)usb_device_cb_bulk_in);
51 /* Start Rx */
52 cdcdf_acm_read((uint8_t *)usbd_cdc_buffer, sizeof(usbd_cdc_buffer));
53 }
54
55 /* No error. */
56 return false;
57}
58
Harald Welte56d45db2019-04-19 22:33:36 +020059extern const struct usbd_descriptors usb_descs[];
60
Harald Welte78bb6952019-05-11 18:05:40 +020061#define USBStringDescriptor_LENGTH(length) ((length) * 2 + 2)
62#define USBStringDescriptor_UNICODE(ascii) (ascii), 0
63#define USBStringDescriptor_ENGLISH_US 0x09, 0x04
64
65static uint8_t usb_str_lang[] = {
66 USBStringDescriptor_LENGTH(1),
67 USB_DT_STRING,
68 USBStringDescriptor_ENGLISH_US,
69};
70
71static uint8_t usb_str_serial[] = {
72 USBStringDescriptor_LENGTH(4),
73 USB_DT_STRING,
74 USBStringDescriptor_UNICODE('1'),
75 USBStringDescriptor_UNICODE('2'),
76 USBStringDescriptor_UNICODE('3'),
77 USBStringDescriptor_UNICODE('4'),
78};
79
80/* transmit given string descriptor */
81static bool send_str_desc(uint8_t ep, const struct usb_req *req, enum usb_ctrl_stage stage,
82 const uint8_t *desc)
83{
84 uint16_t len_req = LE16(req->wLength);
85 uint16_t len_desc = desc[0];
86 uint16_t len_tx;
87 bool need_zlp = !(len_req & (CONF_USB_CDCD_ACM_BMAXPKSZ0 - 1));
88
89 /* we get called twice here: First after SETUP stage and then after DATA stage */
90 if (stage != USB_SETUP_STAGE) {
91 printf("skipping stage %u\r\n", stage);
92 return true;
93 }
94
95 if (len_req <= len_desc) {
96 need_zlp = false;
97 len_tx = len_req;
98 } else {
99 len_tx = len_desc;
100 }
101
102 printf("Sending string %u from callback: ", req->wValue & 0x00ff);
103 printf("ep=0x%02x len_req=%u len_desc=%u, len_tx=%u, zlp=%u\r\n",
104 ep, len_req, len_desc, len_tx, need_zlp);
105
106 if (ERR_NONE != usbdc_xfer(ep, (uint8_t *)desc, len_tx, need_zlp)) {
107 printf("returning false\r\n");
108 return false;
109 }
110
111 printf("returning true\r\n");
112 return true;
113}
114
115/* call-back for every control EP request */
116static int32_t string_req_cb(uint8_t ep, struct usb_req *req, enum usb_ctrl_stage stage)
117{
118 uint8_t index, type;
119
120 if ((req->bmRequestType & (USB_REQT_TYPE_MASK | USB_REQT_DIR_IN)) !=
121 (USB_REQT_TYPE_STANDARD | USB_REQT_DIR_IN))
122 return ERR_NOT_FOUND;
123
124 /* abort if it's not a GET DESCRIPTOR request */
125 if (req->bRequest != USB_REQ_GET_DESC)
126 return ERR_NOT_FOUND;
127
128 /* abort if it's not about a string descriptor */
129 type = req->wValue >> 8;
130 if (type != USB_DT_STRING)
131 return ERR_NOT_FOUND;
132#if 0
133 printf("ep=%02x, bmReqT=%04x, bReq=%02x, wValue=%04x, stage=%d\r\n",
134 ep, req->bmRequestType, req->bRequest, req->wValue, stage);
135#endif
136 /* abort if it's not a standard GET request */
137 index = req->wValue & 0x00FF;
138 switch (index) {
139#if 0
140 case 0:
141 return send_str_desc(ep, req, stage, usb_str_lang);
142#endif
143 case 7: /* STR_DESC_SERIAL */
144 return send_str_desc(ep, req, stage, usb_str_serial);
145 default:
146 return ERR_NOT_FOUND;
147 }
148}
149
150
151static struct usbdc_handler string_req_h = {NULL, (FUNC_PTR)string_req_cb};
152
Kévin Redon69b92d92019-01-24 16:39:20 +0100153/**
154 * \brief CDC ACM Init
155 */
156void cdc_device_acm_init(void)
157{
158 /* usb stack init */
159 usbdc_init(ctrl_buffer);
Harald Welte78bb6952019-05-11 18:05:40 +0200160 usbdc_register_handler(USBDC_HDL_REQ, &string_req_h);
Kévin Redon69b92d92019-01-24 16:39:20 +0100161
162 /* usbdc_register_funcion inside */
163 cdcdf_acm_init();
164
Harald Welte78bb6952019-05-11 18:05:40 +0200165 printf("usb_descs_size=%u\r\n", usb_descs[0].eod - usb_descs[0].sod);
Harald Welte56d45db2019-04-19 22:33:36 +0200166 usbdc_start((struct usbd_descriptors *) usb_descs);
Kévin Redon69b92d92019-01-24 16:39:20 +0100167 usbdc_attach();
168}
169
170/**
Kévin Redon8e538002019-01-30 11:19:19 +0100171 * \brief Start USB stack
Kévin Redon69b92d92019-01-24 16:39:20 +0100172 */
Kévin Redon8e538002019-01-30 11:19:19 +0100173void usb_start(void)
Kévin Redon69b92d92019-01-24 16:39:20 +0100174{
175 while (!cdcdf_acm_is_enabled()) {
176 // wait cdc acm to be installed
177 };
178
179 cdcdf_acm_register_callback(CDCDF_ACM_CB_STATE_C, (FUNC_PTR)usb_device_cb_state_c);
Kévin Redon69b92d92019-01-24 16:39:20 +0100180}
181
182void usb_init(void)
183{
Kévin Redon69b92d92019-01-24 16:39:20 +0100184 cdc_device_acm_init();
Harald Welte9dbacf12019-04-18 17:59:19 +0200185 ccid_df_init();
Kévin Redon69b92d92019-01-24 16:39:20 +0100186}