tinyusb  0.4
Click here to lend your support to tinyusb donation and make a donation at pledgie.com
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Groups Pages
cdc_device.c
Go to the documentation of this file.
1 /**************************************************************************/
37 /**************************************************************************/
38 
39 #include "tusb_option.h"
40 
41 #if (MODE_DEVICE_SUPPORTED && TUSB_CFG_DEVICE_CDC)
42 
43 #define _TINY_USB_SOURCE_FILE_
44 //--------------------------------------------------------------------+
45 // INCLUDE
46 //--------------------------------------------------------------------+
47 #include "common/common.h"
48 #include "cdc_device.h"
49 
50 //--------------------------------------------------------------------+
51 // MACRO CONSTANT TYPEDEF
52 //--------------------------------------------------------------------+
54 static cdc_line_coding_t cdcd_line_coding[CONTROLLER_DEVICE_NUMBER];
55 
56 typedef struct {
57  uint8_t interface_number;
58  cdc_acm_capability_t acm_capability;
59 
60  endpoint_handle_t edpt_hdl[3]; // notification, data in, data out
61 }cdcd_data_t;
62 
63 //--------------------------------------------------------------------+
64 // INTERNAL OBJECT & FUNCTION DECLARATION
65 //--------------------------------------------------------------------+
66 cdcd_data_t cdcd_data[CONTROLLER_DEVICE_NUMBER];
67 
68 static tusb_error_t cdcd_xfer(uint8_t coreid, cdc_pipeid_t pipeid, void * p_buffer, uint32_t length, bool is_notify)
69 {
70  ASSERT(tusbd_is_configured(coreid), TUSB_ERROR_USBD_DEVICE_NOT_CONFIGURED);
71 
72  cdcd_data_t* p_cdc = &cdcd_data[coreid];
73 
74  ASSERT_FALSE ( dcd_pipe_is_busy(p_cdc->edpt_hdl[pipeid]), TUSB_ERROR_INTERFACE_IS_BUSY);
75  ASSERT_STATUS( dcd_pipe_xfer(p_cdc->edpt_hdl[pipeid], p_buffer, length, is_notify) );
76 
77  return TUSB_ERROR_NONE;
78 }
79 
80 //--------------------------------------------------------------------+
81 // APPLICATION API (Parameters requires validation)
82 //--------------------------------------------------------------------+
83 bool tusbd_cdc_is_busy(uint8_t coreid, cdc_pipeid_t pipeid)
84 {
85  return dcd_pipe_is_busy( cdcd_data[coreid].edpt_hdl[pipeid] );
86 }
87 
88 tusb_error_t tusbd_cdc_receive(uint8_t coreid, void * p_buffer, uint32_t length, bool is_notify)
89 {
90  return cdcd_xfer(coreid, CDC_PIPE_DATA_OUT, p_buffer, length, is_notify);
91 }
92 
93 tusb_error_t tusbd_cdc_send(uint8_t coreid, void * p_data, uint32_t length, bool is_notify)
94 {
95  return cdcd_xfer(coreid, CDC_PIPE_DATA_IN, p_data, length, is_notify);
96 }
97 
98 //--------------------------------------------------------------------+
99 // USBD-CLASS API
100 //--------------------------------------------------------------------+
101 void cdcd_init(void)
102 {
103  memclr_(cdcd_data, sizeof(cdcd_data_t)*CONTROLLER_DEVICE_NUMBER);
104 
105  // default line coding is : stop bit = 1, parity = none, data bits = 8
106  memclr_(cdcd_line_coding, sizeof(cdc_line_coding_t)*CONTROLLER_DEVICE_NUMBER);
107  for(uint8_t i=0; i<CONTROLLER_DEVICE_NUMBER; i++) cdcd_line_coding[i].data_bits = 8;
108 }
109 
110 tusb_error_t cdcd_open(uint8_t coreid, tusb_descriptor_interface_t const * p_interface_desc, uint16_t *p_length)
111 {
112  if ( CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL != p_interface_desc->bInterfaceSubClass) return TUSB_ERROR_CDC_UNSUPPORTED_SUBCLASS;
113 
115  0xff == p_interface_desc->bInterfaceProtocol) )
116  {
117  return TUSB_ERROR_CDC_UNSUPPORTED_PROTOCOL;
118  }
119 
120  uint8_t const * p_desc = descriptor_next ( (uint8_t const *) p_interface_desc );
121  cdcd_data_t * p_cdc = &cdcd_data[coreid];
122 
123  //------------- Communication Interface -------------//
124  (*p_length) = sizeof(tusb_descriptor_interface_t);
125 
126  while( TUSB_DESC_TYPE_INTERFACE_CLASS_SPECIFIC == p_desc[DESCRIPTOR_OFFSET_TYPE] )
127  { // Communication Functional Descriptors
128  if ( CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT == cdc_functional_desc_typeof(p_desc) )
129  { // save ACM bmCapabilities
130  p_cdc->acm_capability = ((cdc_desc_func_abstract_control_management_t const *) p_desc)->bmCapabilities;
131  }
132 
133  (*p_length) += p_desc[DESCRIPTOR_OFFSET_LENGTH];
134  p_desc = descriptor_next(p_desc);
135  }
136 
137  if ( TUSB_DESC_TYPE_ENDPOINT == p_desc[DESCRIPTOR_OFFSET_TYPE])
138  { // notification endpoint if any
139  p_cdc->edpt_hdl[CDC_PIPE_NOTIFICATION] = dcd_pipe_open(coreid, (tusb_descriptor_endpoint_t const *) p_desc, TUSB_CLASS_CDC);
140 
141  (*p_length) += p_desc[DESCRIPTOR_OFFSET_LENGTH];
142  p_desc = descriptor_next(p_desc);
143 
144  ASSERT(endpointhandle_is_valid(p_cdc->edpt_hdl[CDC_PIPE_NOTIFICATION]), TUSB_ERROR_DCD_OPEN_PIPE_FAILED);
145  }
146 
147  //------------- Data Interface (if any) -------------//
148  if ( (TUSB_DESC_TYPE_INTERFACE == p_desc[DESCRIPTOR_OFFSET_TYPE]) &&
149  (TUSB_CLASS_CDC_DATA == ((tusb_descriptor_interface_t const *) p_desc)->bInterfaceClass) )
150  {
151  (*p_length) += p_desc[DESCRIPTOR_OFFSET_LENGTH];
152  p_desc = descriptor_next(p_desc);
153 
154  // data endpoints expected to be in pairs
155  for(uint32_t i=0; i<2; i++)
156  {
157  tusb_descriptor_endpoint_t const *p_endpoint = (tusb_descriptor_endpoint_t const *) p_desc;
158  ASSERT_INT(TUSB_DESC_TYPE_ENDPOINT, p_endpoint->bDescriptorType, TUSB_ERROR_DESCRIPTOR_CORRUPTED);
159  ASSERT_INT(TUSB_XFER_BULK, p_endpoint->bmAttributes.xfer, TUSB_ERROR_DESCRIPTOR_CORRUPTED);
160 
161  endpoint_handle_t * p_edpt_hdl = ( p_endpoint->bEndpointAddress & TUSB_DIR_DEV_TO_HOST_MASK ) ?
162  &p_cdc->edpt_hdl[CDC_PIPE_DATA_IN] : &p_cdc->edpt_hdl[CDC_PIPE_DATA_OUT] ;
163 
164  (*p_edpt_hdl) = dcd_pipe_open(coreid, p_endpoint, TUSB_CLASS_CDC);
165  ASSERT ( endpointhandle_is_valid(*p_edpt_hdl), TUSB_ERROR_DCD_OPEN_PIPE_FAILED );
166 
167  (*p_length) += p_desc[DESCRIPTOR_OFFSET_LENGTH];
168  p_desc = descriptor_next( p_desc );
169  }
170  }
171 
172  p_cdc->interface_number = p_interface_desc->bInterfaceNumber;
173 
174  tusbd_cdc_mounted_cb(coreid);
175 
176  return TUSB_ERROR_NONE;
177 }
178 
179 void cdcd_close(uint8_t coreid)
180 {
181  // no need to close opened pipe, dcd bus reset will put controller's endpoints to default state
182  memclr_(&cdcd_data[coreid], sizeof(cdcd_data_t));
183 
184  tusbd_cdc_unmounted_cb(coreid);
185 }
186 
187 tusb_error_t cdcd_control_request_subtask(uint8_t coreid, tusb_control_request_t const * p_request)
188 {
189  //------------- Class Specific Request -------------//
190  if (p_request->bmRequestType_bit.type != TUSB_REQUEST_TYPE_CLASS) return TUSB_ERROR_DCD_CONTROL_REQUEST_NOT_SUPPORT;
191 
192  switch(p_request->bRequest)
193  {
194  case CDC_REQUEST_GET_LINE_CODING:
195  dcd_pipe_control_xfer(coreid, (tusb_direction_t) p_request->bmRequestType_bit.direction,
196  (uint8_t*) &cdcd_line_coding[coreid], min16_of(sizeof(cdc_line_coding_t), p_request->wLength), false );
197  break;
198 
199  case CDC_REQUEST_SET_LINE_CODING:
200  dcd_pipe_control_xfer(coreid, (tusb_direction_t) p_request->bmRequestType_bit.direction,
201  (uint8_t*) &cdcd_line_coding[coreid], min16_of(sizeof(cdc_line_coding_t), p_request->wLength), false );
202  // TODO notify application on xfer completea
203  break;
204 
205  case CDC_REQUEST_SET_CONTROL_LINE_STATE: // TODO extract DTE present
206  break;
207 
208 
209  default: return TUSB_ERROR_DCD_CONTROL_REQUEST_NOT_SUPPORT;
210  }
211 
212  return TUSB_ERROR_NONE;
213 }
214 
215 tusb_error_t cdcd_xfer_cb(endpoint_handle_t edpt_hdl, tusb_event_t event, uint32_t xferred_bytes)
216 {
217  cdcd_data_t const * p_cdc = &cdcd_data[edpt_hdl.coreid];
218 
219  for(cdc_pipeid_t pipeid=CDC_PIPE_NOTIFICATION; pipeid < CDC_PIPE_ERROR; pipeid++ )
220  {
221  if ( endpointhandle_is_equal(edpt_hdl, p_cdc->edpt_hdl[pipeid]) )
222  {
223  tusbd_cdc_xfer_cb(edpt_hdl.coreid, event, pipeid, xferred_bytes);
224  break;
225  }
226  }
227 
228  return TUSB_ERROR_NONE;
229 }
230 
231 #endif
USB Standard Interface Descriptor (section 9.6.1 table 9-12)
Abstract Control Model [USBPSTN1.2].
Definition: cdc.h:71
uint8_t bInterfaceProtocol
Protocol code (assigned by the USB). These codes are qualified by the value of the bInterfaceClass ...
AT Commands: V.250 etc.
Definition: cdc.h:86
void tusbd_cdc_mounted_cb(uint8_t coreid)
Callback function that will be invoked when this interface is mounted (configured) by USB host...
Notification pipe.
Definition: cdc.h:59
bool tusbd_cdc_is_busy(uint8_t coreid, cdc_pipeid_t pipeid) ATTR_PURE ATTR_WARN_UNUSED_RESULT
Check if the interface is currently busy or not.
Data in pipe.
Definition: cdc.h:60
struct tusb_descriptor_endpoint_t::@8 bmAttributes
This field describes the endpoint's attributes when it is configured using the bConfigurationValue. Bits 1..0: Transfer Type - 00 = Control - 01 = Isochronous - 10 = Bulk - 11 = Interrupt If not an isochronous endpoint, bits 5..2 are reserved and must be set to zero. If isochronous, they are defined as follows: Bits 3..2: Synchronization Type - 00 = No Synchronization - 01 = Asynchronous - 10 = Adaptive - 11 = Synchronous Bits 5..4: Usage Type - 00 = Data endpoint - 01 = Feedback endpoint - 10 = Implicit feedback Data endpoint - 11 = Reserved Refer to Chapter 5 of USB 2.0 specification for more information. All other bits are reserved and must be reset to zero. Reserved bits must be ignored by the host.
#define TUSB_CFG_ATTR_USBRAM
void tusbd_cdc_unmounted_cb(uint8_t coreid)
Callback function that will be invoked when this interface is unmounted (bus reset/unplugged) ...
AT Commands defined by TIA for CDMA.
Definition: cdc.h:91
static bool is_in_range(uint32_t lower, uint32_t value, uint32_t upper) ATTR_ALWAYS_INLINE ATTR_CONST
inclusive range checking
Definition: common.h:236
uint8_t bDescriptorType
ENDPOINT Descriptor Type.
uint8_t bInterfaceSubClass
Subclass code (assigned by the USB-IF). These codes are qualified by the value of the bInterfaceCla...
Abstract Control Management Functional Descriptor.
Definition: cdc.h:100
USB Standard Endpoint Descriptor (section 9.6.1 table 9-13)
tusb_error_t tusbd_cdc_receive(uint8_t coreid, void *p_buffer, uint32_t length, bool is_notify)
Submit USB transfer.
Invalid Pipe ID.
Definition: cdc.h:62
void tusbd_cdc_xfer_cb(uint8_t coreid, tusb_event_t event, cdc_pipeid_t pipe_id, uint32_t xferred_bytes)
Callback function that is invoked when an completion (error or success) of an USB transfer previously...
cdc_pipeid_t
CDC Pipe ID, used to indicate which pipe the API is addressing to (Notification, Out, In)
Definition: cdc.h:58
uint8_t bInterfaceNumber
Number of this interface. Zero-based value identifying the index in the array of concurrent interface...
Abstract Control Management Functional Descriptor.
Definition: cdc.h:296
tusb_error_t
Error Code returned.
Definition: tusb_errors.h:100
tusb_error_t tusbd_cdc_send(uint8_t coreid, void *p_data, uint32_t length, bool is_notify)
Submit USB transfer.
Data out pipe.
Definition: cdc.h:61
uint8_t bEndpointAddress
The address of the endpoint on the USB device described by this descriptor. The address is encoded as...