USB Host Shield 2.0
cdcacm.cpp
Go to the documentation of this file.
1 /* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
2 
3 This software may be distributed and modified under the terms of the GNU
4 General Public License version 2 (GPL2) as published by the Free Software
5 Foundation and appearing in the file GPL2.TXT included in the packaging of
6 this file. Please note that GPL2 Section 2[b] requires that all works based
7 on this software must also be made publicly available under the terms of
8 the GPL2 ("Copyleft").
9 
10 Contact information
11 -------------------
12 
13 Circuits At Home, LTD
14 Web : http://www.circuitsathome.com
15 e-mail : support@circuitsathome.com
16  */
17 #include "cdcacm.h"
18 
19 const uint8_t ACM::epDataInIndex = 1;
20 const uint8_t ACM::epDataOutIndex = 2;
21 const uint8_t ACM::epInterruptInIndex = 3;
22 
23 ACM::ACM(USB *p, CDCAsyncOper *pasync) :
24 pUsb(p),
25 pAsync(pasync),
26 bAddress(0),
27 bControlIface(0),
28 bDataIface(0),
29 bNumEP(1),
30 qNextPollTime(0),
31 bPollEnable(false),
32 ready(false) {
33  _enhanced_status = enhanced_features(); // Set up features
34  for(uint8_t i = 0; i < ACM_MAX_ENDPOINTS; i++) {
35  epInfo[i].epAddr = 0;
36  epInfo[i].maxPktSize = (i) ? 0 : 8;
37  epInfo[i].epAttribs = 0;
39 
40  }
41  if(pUsb)
43 }
44 
45 uint8_t ACM::Init(uint8_t parent, uint8_t port, bool lowspeed) {
46 
47  const uint8_t constBufSize = sizeof (USB_DEVICE_DESCRIPTOR);
48 
49  uint8_t buf[constBufSize];
50  USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast<USB_DEVICE_DESCRIPTOR*>(buf);
51 
52  uint8_t rcode;
53  UsbDevice *p = NULL;
54  EpInfo *oldep_ptr = NULL;
55  uint8_t num_of_conf; // number of configurations
56 
57  AddressPool &addrPool = pUsb->GetAddressPool();
58 
59  USBTRACE("ACM Init\r\n");
60 
61  if(bAddress)
63 
64  // Get pointer to pseudo device with address 0 assigned
65  p = addrPool.GetUsbDevicePtr(0);
66 
67  if(!p)
69 
70  if(!p->epinfo) {
71  USBTRACE("epinfo\r\n");
73  }
74 
75  // Save old pointer to EP_RECORD of address 0
76  oldep_ptr = p->epinfo;
77 
78  // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence
79  p->epinfo = epInfo;
80 
81  p->lowspeed = lowspeed;
82 
83  // Get device descriptor
84  rcode = pUsb->getDevDescr(0, 0, constBufSize, (uint8_t*)buf);
85 
86  // Restore p->epinfo
87  p->epinfo = oldep_ptr;
88 
89  if(rcode)
90  goto FailGetDevDescr;
91 
92  // Allocate new address according to device class
93  bAddress = addrPool.AllocAddress(parent, false, port);
94 
95  if(!bAddress)
97 
98  // Extract Max Packet Size from the device descriptor
100 
101  // Assign new address to the device
102  rcode = pUsb->setAddr(0, 0, bAddress);
103 
104  if(rcode) {
105  p->lowspeed = false;
106  addrPool.FreeAddress(bAddress);
107  bAddress = 0;
108  USBTRACE2("setAddr:", rcode);
109  return rcode;
110  }
111 
112  USBTRACE2("Addr:", bAddress);
113 
114  p->lowspeed = false;
115 
116  p = addrPool.GetUsbDevicePtr(bAddress);
117 
118  if(!p)
120 
121  p->lowspeed = lowspeed;
122 
123  num_of_conf = udd->bNumConfigurations;
124 
125  // Assign epInfo to epinfo pointer
126  rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo);
127 
128  if(rcode)
129  goto FailSetDevTblEntry;
130 
131  USBTRACE2("NC:", num_of_conf);
132 
133  for(uint8_t i = 0; i < num_of_conf; i++) {
139  CP_MASK_COMPARE_PROTOCOL > CdcControlParser(this);
140 
142  CP_MASK_COMPARE_CLASS> CdcDataParser(this);
143 
144  rcode = pUsb->getConfDescr(bAddress, 0, i, &CdcControlParser);
145 
146  if(rcode)
147  goto FailGetConfDescr;
148 
149  rcode = pUsb->getConfDescr(bAddress, 0, i, &CdcDataParser);
150 
151  if(rcode)
152  goto FailGetConfDescr;
153 
154  if(bNumEP > 1)
155  break;
156  } // for
157 
158  if(bNumEP < 4)
160 
161  // Assign epInfo to epinfo pointer
163 
164  USBTRACE2("Conf:", bConfNum);
165 
166  // Set Configuration Value
167  rcode = pUsb->setConf(bAddress, 0, bConfNum);
168 
169  if(rcode)
170  goto FailSetConfDescr;
171 
172  // Set up features status
174  half_duplex(false);
175  autoflowRTS(false);
176  autoflowDSR(false);
177  autoflowXON(false);
178  wide(false); // Always false, because this is only available in custom mode.
179  rcode = pAsync->OnInit(this);
180 
181  if(rcode)
182  goto FailOnInit;
183 
184  USBTRACE("ACM configured\r\n");
185 
186  ready = true;
187 
188  //bPollEnable = true;
189 
190  //USBTRACE("Poll enabled\r\n");
191  return 0;
192 
193 FailGetDevDescr:
194 #ifdef DEBUG_USB_HOST
196  goto Fail;
197 #endif
198 
199 FailSetDevTblEntry:
200 #ifdef DEBUG_USB_HOST
202  goto Fail;
203 #endif
204 
205 FailGetConfDescr:
206 #ifdef DEBUG_USB_HOST
208  goto Fail;
209 #endif
210 
211 FailSetConfDescr:
212 #ifdef DEBUG_USB_HOST
214  goto Fail;
215 #endif
216 
217 FailOnInit:
218 #ifdef DEBUG_USB_HOST
219  USBTRACE("OnInit:");
220 #endif
221 
222 #ifdef DEBUG_USB_HOST
223 Fail:
224  NotifyFail(rcode);
225 #endif
226  Release();
227  return rcode;
228 }
229 
230 void ACM::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *pep) {
231  //ErrorMessage<uint8_t > (PSTR("Conf.Val"), conf);
232  //ErrorMessage<uint8_t > (PSTR("Iface Num"), iface);
233  //ErrorMessage<uint8_t > (PSTR("Alt.Set"), alt);
234 
235  bConfNum = conf;
236 
237  uint8_t index;
238 
239  if((pep->bmAttributes & 0x03) == 3 && (pep->bEndpointAddress & 0x80) == 0x80)
240  index = epInterruptInIndex;
241  else
242  if((pep->bmAttributes & 0x02) == 2)
243  index = ((pep->bEndpointAddress & 0x80) == 0x80) ? epDataInIndex : epDataOutIndex;
244  else
245  return;
246 
247  // Fill in the endpoint info structure
248  epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F);
249  epInfo[index].maxPktSize = (uint8_t)pep->wMaxPacketSize;
250  epInfo[index].epAttribs = 0;
251 
252  bNumEP++;
253 
255 }
256 
257 uint8_t ACM::Release() {
258  ready = false;
260 
261  bControlIface = 0;
262  bDataIface = 0;
263  bNumEP = 1;
264 
265  bAddress = 0;
266  qNextPollTime = 0;
267  bPollEnable = false;
268  return 0;
269 }
270 
271 uint8_t ACM::Poll() {
272  uint8_t rcode = 0;
273 
274  if(!bPollEnable)
275  return 0;
276 
277  return rcode;
278 }
279 
280 uint8_t ACM::RcvData(uint16_t *bytes_rcvd, uint8_t *dataptr) {
281  return pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, bytes_rcvd, dataptr);
282 }
283 
284 uint8_t ACM::SndData(uint16_t nbytes, uint8_t *dataptr) {
285  return pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, nbytes, dataptr);
286 }
287 
288 uint8_t ACM::SetCommFeature(uint16_t fid, uint8_t nbytes, uint8_t *dataptr) {
289  return ( pUsb->ctrlReq(bAddress, 0, bmREQ_CDCOUT, CDC_SET_COMM_FEATURE, (fid & 0xff), (fid >> 8), bControlIface, nbytes, nbytes, dataptr, NULL));
290 }
291 
292 uint8_t ACM::GetCommFeature(uint16_t fid, uint8_t nbytes, uint8_t *dataptr) {
293  return ( pUsb->ctrlReq(bAddress, 0, bmREQ_CDCIN, CDC_GET_COMM_FEATURE, (fid & 0xff), (fid >> 8), bControlIface, nbytes, nbytes, dataptr, NULL));
294 }
295 
296 uint8_t ACM::ClearCommFeature(uint16_t fid) {
297  return ( pUsb->ctrlReq(bAddress, 0, bmREQ_CDCOUT, CDC_CLEAR_COMM_FEATURE, (fid & 0xff), (fid >> 8), bControlIface, 0, 0, NULL, NULL));
298 }
299 
300 uint8_t ACM::SetLineCoding(const LINE_CODING *dataptr) {
301  return ( pUsb->ctrlReq(bAddress, 0, bmREQ_CDCOUT, CDC_SET_LINE_CODING, 0x00, 0x00, bControlIface, sizeof (LINE_CODING), sizeof (LINE_CODING), (uint8_t*)dataptr, NULL));
302 }
303 
304 uint8_t ACM::GetLineCoding(LINE_CODING *dataptr) {
305  return ( pUsb->ctrlReq(bAddress, 0, bmREQ_CDCIN, CDC_GET_LINE_CODING, 0x00, 0x00, bControlIface, sizeof (LINE_CODING), sizeof (LINE_CODING), (uint8_t*)dataptr, NULL));
306 }
307 
308 uint8_t ACM::SetControlLineState(uint8_t state) {
309  return ( pUsb->ctrlReq(bAddress, 0, bmREQ_CDCOUT, CDC_SET_CONTROL_LINE_STATE, state, 0, bControlIface, 0, 0, NULL, NULL));
310 }
311 
312 uint8_t ACM::SendBreak(uint16_t duration) {
313  return ( pUsb->ctrlReq(bAddress, 0, bmREQ_CDCOUT, CDC_SEND_BREAK, (duration & 0xff), (duration >> 8), bControlIface, 0, 0, NULL, NULL));
314 }
315 
317  Notify(PSTR("Endpoint descriptor:"), 0x80);
318  Notify(PSTR("\r\nLength:\t\t"), 0x80);
319  D_PrintHex<uint8_t > (ep_ptr->bLength, 0x80);
320  Notify(PSTR("\r\nType:\t\t"), 0x80);
321  D_PrintHex<uint8_t > (ep_ptr->bDescriptorType, 0x80);
322  Notify(PSTR("\r\nAddress:\t"), 0x80);
323  D_PrintHex<uint8_t > (ep_ptr->bEndpointAddress, 0x80);
324  Notify(PSTR("\r\nAttributes:\t"), 0x80);
325  D_PrintHex<uint8_t > (ep_ptr->bmAttributes, 0x80);
326  Notify(PSTR("\r\nMaxPktSize:\t"), 0x80);
327  D_PrintHex<uint16_t > (ep_ptr->wMaxPacketSize, 0x80);
328  Notify(PSTR("\r\nPoll Intrv:\t"), 0x80);
329  D_PrintHex<uint8_t > (ep_ptr->bInterval, 0x80);
330  Notify(PSTR("\r\n"), 0x80);
331 }
#define USB_CLASS_COM_AND_CDC_CTRL
Definition: UsbCore.h:58
#define USB_CLASS_CDC_DATA
Definition: UsbCore.h:65
uint8_t getConfDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t conf, uint8_t *dataptr)
Definition: Usb.cpp:769
#define CDC_SUBCLASS_ACM
Definition: cdcacm.h:27
virtual tty_features enhanced_features(void)
Definition: cdcacm.h:222
ACM(USB *pusb, CDCAsyncOper *pasync)
Definition: cdcacm.cpp:23
#define CDC_PROTOCOL_ITU_T_V_250
Definition: cdcacm.h:40
EpInfo * epinfo
Definition: address.h:76
#define CP_MASK_COMPARE_PROTOCOL
bool lowspeed
Definition: address.h:79
#define USB_ERROR_EPINFO_IS_NULL
Definition: UsbCore.h:83
virtual uint8_t OnInit(ACM *pacm)
Definition: cdcacm.h:131
static const uint8_t epInterruptInIndex
Definition: cdcacm.h:167
uint8_t bmNakPower
Definition: address.h:42
static const uint8_t epDataOutIndex
Definition: cdcacm.h:166
#define CDC_CLEAR_COMM_FEATURE
Definition: cdcacm.h:55
uint32_t qNextPollTime
Definition: cdcacm.h:176
uint8_t bControlIface
Definition: cdcacm.h:173
#define CDC_SET_COMM_FEATURE
Definition: cdcacm.h:53
#define CDC_SET_LINE_CODING
Definition: cdcacm.h:62
uint8_t bMaxPacketSize0
Definition: usb_ch9.h:105
volatile bool ready
Definition: cdcacm.h:178
#define NotifyFail(...)
Definition: message.h:55
uint8_t bDataIface
Definition: cdcacm.h:174
USB * pUsb
Definition: cdcacm.h:169
virtual void autoflowRTS(bool s)
Definition: cdcacm.h:233
uint8_t setConf(uint8_t addr, uint8_t ep, uint8_t conf_value)
Definition: Usb.cpp:808
uint8_t bNumEP
Definition: cdcacm.h:175
#define bmREQ_CDCOUT
Definition: cdcacm.h:22
EpInfo epInfo[ACM_MAX_ENDPOINTS]
Definition: cdcacm.h:181
#define NotifyFailGetDevDescr(...)
Definition: message.h:50
uint8_t setEpInfoEntry(uint8_t addr, uint8_t epcount, EpInfo *eprecord_ptr)
Definition: Usb.cpp:64
#define CP_MASK_COMPARE_CLASS
#define CDC_SEND_BREAK
Definition: cdcacm.h:65
#define CDC_GET_COMM_FEATURE
Definition: cdcacm.h:54
virtual void FreeAddress(uint8_t addr)=0
uint8_t epAttribs
Definition: address.h:37
uint8_t ctrlReq(uint8_t addr, uint8_t ep, uint8_t bmReqType, uint8_t bRequest, uint8_t wValLo, uint8_t wValHi, uint16_t wInd, uint16_t total, uint16_t nbytes, uint8_t *dataptr, USBReadParser *p)
Definition: Usb.cpp:126
virtual UsbDevice * GetUsbDevicePtr(uint8_t addr)=0
void PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR *ep_ptr)
Definition: cdcacm.cpp:316
#define Notify(...)
Definition: message.h:44
CDCAsyncOper * pAsync
Definition: cdcacm.h:170
#define USBTRACE2(s, r)
Definition: macros.h:77
uint8_t setAddr(uint8_t oldaddr, uint8_t ep, uint8_t newaddr)
Definition: Usb.cpp:799
#define ACM_MAX_ENDPOINTS
Definition: cdcacm.h:161
#define NotifyFailGetConfDescr(...)
Definition: message.h:52
virtual void wide(bool s)
Definition: cdcacm.h:245
uint8_t GetLineCoding(LINE_CODING *dataptr)
Definition: cdcacm.cpp:304
uint8_t epAddr
Definition: address.h:33
#define USB_NAK_MAX_POWER
Definition: address.h:27
virtual void autoflowXON(bool s)
Definition: cdcacm.h:239
#define bmREQ_CDCIN
Definition: cdcacm.h:23
uint8_t SndData(uint16_t nbytes, uint8_t *dataptr)
Definition: cdcacm.cpp:284
uint8_t Poll()
Definition: cdcacm.cpp:271
Definition: address.h:32
#define CDC_GET_LINE_CODING
Definition: cdcacm.h:63
uint8_t outTransfer(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t *data)
Definition: Usb.cpp:292
uint16_t wMaxPacketSize
Definition: usb_ch9.h:146
uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed)
Definition: cdcacm.cpp:45
#define CP_MASK_COMPARE_SUBCLASS
virtual uint8_t AllocAddress(uint8_t parent, bool is_hub=false, uint8_t port=0)=0
uint8_t bEndpointAddress
Definition: usb_ch9.h:144
static const uint8_t epDataInIndex
Definition: cdcacm.h:165
virtual void autoflowDSR(bool s)
Definition: cdcacm.h:236
uint8_t bAddress
Definition: cdcacm.h:171
#define USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE
Definition: UsbCore.h:85
#define PSTR(str)
uint8_t SetLineCoding(const LINE_CODING *dataptr)
Definition: cdcacm.cpp:300
void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep)
Definition: cdcacm.cpp:230
#define USB_NAK_NOWAIT
Definition: address.h:29
uint8_t SendBreak(uint16_t duration)
Definition: cdcacm.cpp:312
#define USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL
Definition: UsbCore.h:82
uint8_t inTransfer(uint8_t addr, uint8_t ep, uint16_t *nbytesptr, uint8_t *data)
Definition: Usb.cpp:206
#define USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED
Definition: UsbCore.h:77
uint8_t GetCommFeature(uint16_t fid, uint8_t nbytes, uint8_t *dataptr)
Definition: cdcacm.cpp:292
uint8_t Release()
Definition: cdcacm.cpp:257
uint8_t bConfNum
Definition: cdcacm.h:172
uint8_t bNumConfigurations
Definition: usb_ch9.h:112
#define USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL
Definition: UsbCore.h:80
#define CDC_SET_CONTROL_LINE_STATE
Definition: cdcacm.h:64
uint8_t maxPktSize
Definition: address.h:34
AddressPool & GetAddressPool()
Definition: UsbCore.h:213
Definition: UsbCore.h:197
volatile bool bPollEnable
Definition: cdcacm.h:177
uint8_t RegisterDeviceClass(USBDeviceConfig *pdev)
Definition: UsbCore.h:217
#define NotifyFailSetConfDescr(...)
Definition: message.h:53
tty_features _enhanced_status
Definition: cdcacm.h:179
uint8_t SetControlLineState(uint8_t state)
Definition: cdcacm.cpp:308
uint8_t SetCommFeature(uint16_t fid, uint8_t nbytes, uint8_t *dataptr)
Definition: cdcacm.cpp:288
uint8_t ClearCommFeature(uint16_t fid)
Definition: cdcacm.cpp:296
virtual void half_duplex(bool s)
Definition: cdcacm.h:242
#define USBTRACE(s)
Definition: macros.h:75
uint8_t getDevDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t *dataptr)
defined(USB_METHODS_INLINE)
Definition: Usb.cpp:764
#define NotifyFailSetDevTblEntry(...)
Definition: message.h:51
uint8_t RcvData(uint16_t *nbytesptr, uint8_t *dataptr)
Definition: cdcacm.cpp:280