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].bmSndToggle = 0;
38  epInfo[i].bmRcvToggle = 0;
40 
41  }
42  if(pUsb)
44 }
45 
46 uint8_t ACM::Init(uint8_t parent, uint8_t port, bool lowspeed) {
47 
48  const uint8_t constBufSize = sizeof (USB_DEVICE_DESCRIPTOR);
49 
50  uint8_t buf[constBufSize];
51  USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast<USB_DEVICE_DESCRIPTOR*>(buf);
52 
53  uint8_t rcode;
54  UsbDevice *p = NULL;
55  EpInfo *oldep_ptr = NULL;
56  uint8_t num_of_conf; // number of configurations
57 
58  AddressPool &addrPool = pUsb->GetAddressPool();
59 
60  USBTRACE("ACM Init\r\n");
61 
62  if(bAddress)
64 
65  // Get pointer to pseudo device with address 0 assigned
66  p = addrPool.GetUsbDevicePtr(0);
67 
68  if(!p)
70 
71  if(!p->epinfo) {
72  USBTRACE("epinfo\r\n");
74  }
75 
76  // Save old pointer to EP_RECORD of address 0
77  oldep_ptr = p->epinfo;
78 
79  // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence
80  p->epinfo = epInfo;
81 
82  p->lowspeed = lowspeed;
83 
84  // Get device descriptor
85  rcode = pUsb->getDevDescr(0, 0, constBufSize, (uint8_t*)buf);
86 
87  // Restore p->epinfo
88  p->epinfo = oldep_ptr;
89 
90  if(rcode)
91  goto FailGetDevDescr;
92 
93  // Allocate new address according to device class
94  bAddress = addrPool.AllocAddress(parent, false, port);
95 
96  if(!bAddress)
98 
99  // Extract Max Packet Size from the device descriptor
101 
102  // Assign new address to the device
103  rcode = pUsb->setAddr(0, 0, bAddress);
104 
105  if(rcode) {
106  p->lowspeed = false;
107  addrPool.FreeAddress(bAddress);
108  bAddress = 0;
109  USBTRACE2("setAddr:", rcode);
110  return rcode;
111  }
112 
113  USBTRACE2("Addr:", bAddress);
114 
115  p->lowspeed = false;
116 
117  p = addrPool.GetUsbDevicePtr(bAddress);
118 
119  if(!p)
121 
122  p->lowspeed = lowspeed;
123 
124  num_of_conf = udd->bNumConfigurations;
125 
126  // Assign epInfo to epinfo pointer
127  rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo);
128 
129  if(rcode)
130  goto FailSetDevTblEntry;
131 
132  USBTRACE2("NC:", num_of_conf);
133 
134  for(uint8_t i = 0; i < num_of_conf; i++) {
140  CP_MASK_COMPARE_PROTOCOL > CdcControlParser(this);
141 
143  CP_MASK_COMPARE_CLASS> CdcDataParser(this);
144 
145  rcode = pUsb->getConfDescr(bAddress, 0, i, &CdcControlParser);
146 
147  if(rcode)
148  goto FailGetConfDescr;
149 
150  rcode = pUsb->getConfDescr(bAddress, 0, i, &CdcDataParser);
151 
152  if(rcode)
153  goto FailGetConfDescr;
154 
155  if(bNumEP > 1)
156  break;
157  } // for
158 
159  if(bNumEP < 4)
161 
162  // Assign epInfo to epinfo pointer
164 
165  USBTRACE2("Conf:", bConfNum);
166 
167  // Set Configuration Value
168  rcode = pUsb->setConf(bAddress, 0, bConfNum);
169 
170  if(rcode)
171  goto FailSetConfDescr;
172 
173  // Set up features status
175  half_duplex(false);
176  autoflowRTS(false);
177  autoflowDSR(false);
178  autoflowXON(false);
179  wide(false); // Always false, because this is only available in custom mode.
180  rcode = pAsync->OnInit(this);
181 
182  if(rcode)
183  goto FailOnInit;
184 
185  USBTRACE("ACM configured\r\n");
186 
187  ready = true;
188 
189  //bPollEnable = true;
190 
191  //USBTRACE("Poll enabled\r\n");
192  return 0;
193 
194 FailGetDevDescr:
195 #ifdef DEBUG_USB_HOST
197  goto Fail;
198 #endif
199 
200 FailSetDevTblEntry:
201 #ifdef DEBUG_USB_HOST
203  goto Fail;
204 #endif
205 
206 FailGetConfDescr:
207 #ifdef DEBUG_USB_HOST
209  goto Fail;
210 #endif
211 
212 FailSetConfDescr:
213 #ifdef DEBUG_USB_HOST
215  goto Fail;
216 #endif
217 
218 FailOnInit:
219 #ifdef DEBUG_USB_HOST
220  USBTRACE("OnInit:");
221 #endif
222 
223 #ifdef DEBUG_USB_HOST
224 Fail:
225  NotifyFail(rcode);
226 #endif
227  Release();
228  return rcode;
229 }
230 
231 void ACM::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *pep) {
232  //ErrorMessage<uint8_t > (PSTR("Conf.Val"), conf);
233  //ErrorMessage<uint8_t > (PSTR("Iface Num"), iface);
234  //ErrorMessage<uint8_t > (PSTR("Alt.Set"), alt);
235 
236  bConfNum = conf;
237 
238  uint8_t index;
239 
240  if((pep->bmAttributes & 0x03) == 3 && (pep->bEndpointAddress & 0x80) == 0x80)
241  index = epInterruptInIndex;
242  else
243  if((pep->bmAttributes & 0x02) == 2)
244  index = ((pep->bEndpointAddress & 0x80) == 0x80) ? epDataInIndex : epDataOutIndex;
245  else
246  return;
247 
248  // Fill in the endpoint info structure
249  epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F);
250  epInfo[index].maxPktSize = (uint8_t)pep->wMaxPacketSize;
251  epInfo[index].bmSndToggle = 0;
252  epInfo[index].bmRcvToggle = 0;
253 
254  bNumEP++;
255 
257 }
258 
259 uint8_t ACM::Release() {
260  ready = false;
262 
263  bControlIface = 0;
264  bDataIface = 0;
265  bNumEP = 1;
266 
267  bAddress = 0;
268  qNextPollTime = 0;
269  bPollEnable = false;
270  return 0;
271 }
272 
273 uint8_t ACM::Poll() {
274  uint8_t rcode = 0;
275 
276  if(!bPollEnable)
277  return 0;
278 
279  return rcode;
280 }
281 
282 uint8_t ACM::RcvData(uint16_t *bytes_rcvd, uint8_t *dataptr) {
283  return pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, bytes_rcvd, dataptr);
284 }
285 
286 uint8_t ACM::SndData(uint16_t nbytes, uint8_t *dataptr) {
287  return pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, nbytes, dataptr);
288 }
289 
290 uint8_t ACM::SetCommFeature(uint16_t fid, uint8_t nbytes, uint8_t *dataptr) {
291  return ( pUsb->ctrlReq(bAddress, 0, bmREQ_CDCOUT, CDC_SET_COMM_FEATURE, (fid & 0xff), (fid >> 8), bControlIface, nbytes, nbytes, dataptr, NULL));
292 }
293 
294 uint8_t ACM::GetCommFeature(uint16_t fid, uint8_t nbytes, uint8_t *dataptr) {
295  return ( pUsb->ctrlReq(bAddress, 0, bmREQ_CDCIN, CDC_GET_COMM_FEATURE, (fid & 0xff), (fid >> 8), bControlIface, nbytes, nbytes, dataptr, NULL));
296 }
297 
298 uint8_t ACM::ClearCommFeature(uint16_t fid) {
299  return ( pUsb->ctrlReq(bAddress, 0, bmREQ_CDCOUT, CDC_CLEAR_COMM_FEATURE, (fid & 0xff), (fid >> 8), bControlIface, 0, 0, NULL, NULL));
300 }
301 
302 uint8_t ACM::SetLineCoding(const LINE_CODING *dataptr) {
303  return ( pUsb->ctrlReq(bAddress, 0, bmREQ_CDCOUT, CDC_SET_LINE_CODING, 0x00, 0x00, bControlIface, sizeof (LINE_CODING), sizeof (LINE_CODING), (uint8_t*)dataptr, NULL));
304 }
305 
306 uint8_t ACM::GetLineCoding(LINE_CODING *dataptr) {
307  return ( pUsb->ctrlReq(bAddress, 0, bmREQ_CDCIN, CDC_GET_LINE_CODING, 0x00, 0x00, bControlIface, sizeof (LINE_CODING), sizeof (LINE_CODING), (uint8_t*)dataptr, NULL));
308 }
309 
310 uint8_t ACM::SetControlLineState(uint8_t state) {
311  return ( pUsb->ctrlReq(bAddress, 0, bmREQ_CDCOUT, CDC_SET_CONTROL_LINE_STATE, state, 0, bControlIface, 0, 0, NULL, NULL));
312 }
313 
314 uint8_t ACM::SendBreak(uint16_t duration) {
315  return ( pUsb->ctrlReq(bAddress, 0, bmREQ_CDCOUT, CDC_SEND_BREAK, (duration & 0xff), (duration >> 8), bControlIface, 0, 0, NULL, NULL));
316 }
317 
319  Notify(PSTR("Endpoint descriptor:"), 0x80);
320  Notify(PSTR("\r\nLength:\t\t"), 0x80);
321  D_PrintHex<uint8_t > (ep_ptr->bLength, 0x80);
322  Notify(PSTR("\r\nType:\t\t"), 0x80);
323  D_PrintHex<uint8_t > (ep_ptr->bDescriptorType, 0x80);
324  Notify(PSTR("\r\nAddress:\t"), 0x80);
325  D_PrintHex<uint8_t > (ep_ptr->bEndpointAddress, 0x80);
326  Notify(PSTR("\r\nAttributes:\t"), 0x80);
327  D_PrintHex<uint8_t > (ep_ptr->bmAttributes, 0x80);
328  Notify(PSTR("\r\nMaxPktSize:\t"), 0x80);
329  D_PrintHex<uint16_t > (ep_ptr->wMaxPacketSize, 0x80);
330  Notify(PSTR("\r\nPoll Intrv:\t"), 0x80);
331  D_PrintHex<uint8_t > (ep_ptr->bInterval, 0x80);
332  Notify(PSTR("\r\n"), 0x80);
333 }
#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:771
uint8_t bmRcvToggle
Definition: address.h:41
#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:810
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 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:318
#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:801
#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:306
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:286
uint8_t Poll()
Definition: cdcacm.cpp:273
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:293
uint16_t wMaxPacketSize
Definition: usb_ch9.h:146
uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed)
Definition: cdcacm.cpp:46
#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
uint8_t bmSndToggle
Definition: address.h:40
#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:302
void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep)
Definition: cdcacm.cpp:231
#define USB_NAK_NOWAIT
Definition: address.h:29
uint8_t SendBreak(uint16_t duration)
Definition: cdcacm.cpp:314
#define USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL
Definition: UsbCore.h:82
#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:294
uint8_t Release()
Definition: cdcacm.cpp:259
uint8_t inTransfer(uint8_t addr, uint8_t ep, uint16_t *nbytesptr, uint8_t *data, uint8_t bInterval=0)
Definition: Usb.cpp:206
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:310
uint8_t SetCommFeature(uint16_t fid, uint8_t nbytes, uint8_t *dataptr)
Definition: cdcacm.cpp:290
uint8_t ClearCommFeature(uint16_t fid)
Definition: cdcacm.cpp:298
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:766
#define NotifyFailSetDevTblEntry(...)
Definition: message.h:51
uint8_t RcvData(uint16_t *nbytesptr, uint8_t *dataptr)
Definition: cdcacm.cpp:282