USB Host Shield 2.0
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
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  for(uint8_t i = 0; i < ACM_MAX_ENDPOINTS; i++) {
34  epInfo[i].epAddr = 0;
35  epInfo[i].maxPktSize = (i) ? 0 : 8;
36  epInfo[i].epAttribs = 0;
37  //epInfo[i].bmNakPower = USB_NAK_NOWAIT;
39 
40  //if (!i)
42  }
43  if(pUsb)
45 }
46 
47 uint8_t ACM::Init(uint8_t parent, uint8_t port, bool lowspeed) {
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  rcode = pAsync->OnInit(this);
174 
175  if(rcode)
176  goto FailOnInit;
177 
178  USBTRACE("ACM configured\r\n");
179 
180  ready = true;
181 
182  //bPollEnable = true;
183 
184  //USBTRACE("Poll enabled\r\n");
185  return 0;
186 
187 FailGetDevDescr:
188 #ifdef DEBUG_USB_HOST
190  goto Fail;
191 #endif
192 
193 FailSetDevTblEntry:
194 #ifdef DEBUG_USB_HOST
196  goto Fail;
197 #endif
198 
199 FailGetConfDescr:
200 #ifdef DEBUG_USB_HOST
202  goto Fail;
203 #endif
204 
205 FailSetConfDescr:
206 #ifdef DEBUG_USB_HOST
208  goto Fail;
209 #endif
210 
211 FailOnInit:
212 #ifdef DEBUG_USB_HOST
213  USBTRACE("OnInit:");
214 #endif
215 
216 #ifdef DEBUG_USB_HOST
217 Fail:
218  NotifyFail(rcode);
219 #endif
220  Release();
221  return rcode;
222 }
223 
224 void ACM::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *pep) {
225  ErrorMessage<uint8_t > (PSTR("Conf.Val"), conf);
226  ErrorMessage<uint8_t > (PSTR("Iface Num"), iface);
227  ErrorMessage<uint8_t > (PSTR("Alt.Set"), alt);
228 
229  bConfNum = conf;
230 
231  uint8_t index;
232 
233  if((pep->bmAttributes & 0x03) == 3 && (pep->bEndpointAddress & 0x80) == 0x80)
234  index = epInterruptInIndex;
235  else
236  if((pep->bmAttributes & 0x02) == 2)
237  index = ((pep->bEndpointAddress & 0x80) == 0x80) ? epDataInIndex : epDataOutIndex;
238  else
239  return;
240 
241  // Fill in the endpoint info structure
242  epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F);
243  epInfo[index].maxPktSize = (uint8_t)pep->wMaxPacketSize;
244  epInfo[index].epAttribs = 0;
245 
246  bNumEP++;
247 
249 }
250 
251 uint8_t ACM::Release() {
253 
254  bControlIface = 0;
255  bDataIface = 0;
256  bNumEP = 1;
257 
258  bAddress = 0;
259  qNextPollTime = 0;
260  bPollEnable = false;
261  return 0;
262 }
263 
264 uint8_t ACM::Poll() {
265  uint8_t rcode = 0;
266 
267  if(!bPollEnable)
268  return 0;
269 
270  //uint32_t time_now = millis();
271 
272  //if (qNextPollTime <= time_now)
273  //{
274  // qNextPollTime = time_now + 100;
275 
276  // uint8_t rcode;
277  // const uint8_t constBufSize = 16;
278  // uint8_t buf[constBufSize];
279 
280  // for (uint8_t i=0; i<constBufSize; i++)
281  // buf[i] = 0;
282 
283  // uint16_t read = (constBufSize > epInfo[epInterruptInIndex].maxPktSize)
284  // ? epInfo[epInterruptInIndex].maxPktSize : constBufSize;
285  // rcode = pUsb->inTransfer(bAddress, epInfo[epInterruptInIndex].epAddr, &read, buf);
286 
287  // if (rcode)
288  // return rcode;
289 
290  // for (uint8_t i=0; i<read; i++)
291  // {
292  // PrintHex<uint8_t>(buf[i]);
293  // USB_HOST_SERIAL.print(" ");
294  // }
295  // USBTRACE("\r\n");
296  //}
297  return rcode;
298 }
299 
300 uint8_t ACM::RcvData(uint16_t *bytes_rcvd, uint8_t *dataptr) {
301  return pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, bytes_rcvd, dataptr);
302 }
303 
304 uint8_t ACM::SndData(uint16_t nbytes, uint8_t *dataptr) {
305  return pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, nbytes, dataptr);
306 }
307 
308 uint8_t ACM::SetCommFeature(uint16_t fid, uint8_t nbytes, uint8_t *dataptr) {
309  return ( pUsb->ctrlReq(bAddress, 0, bmREQ_CDCOUT, CDC_SET_COMM_FEATURE, (fid & 0xff), (fid >> 8), bControlIface, nbytes, nbytes, dataptr, NULL));
310 }
311 
312 uint8_t ACM::GetCommFeature(uint16_t fid, uint8_t nbytes, uint8_t *dataptr) {
313  return ( pUsb->ctrlReq(bAddress, 0, bmREQ_CDCIN, CDC_GET_COMM_FEATURE, (fid & 0xff), (fid >> 8), bControlIface, nbytes, nbytes, dataptr, NULL));
314 }
315 
316 uint8_t ACM::ClearCommFeature(uint16_t fid) {
317  return ( pUsb->ctrlReq(bAddress, 0, bmREQ_CDCOUT, CDC_CLEAR_COMM_FEATURE, (fid & 0xff), (fid >> 8), bControlIface, 0, 0, NULL, NULL));
318 }
319 
320 uint8_t ACM::SetLineCoding(const LINE_CODING *dataptr) {
321  return ( pUsb->ctrlReq(bAddress, 0, bmREQ_CDCOUT, CDC_SET_LINE_CODING, 0x00, 0x00, bControlIface, sizeof (LINE_CODING), sizeof (LINE_CODING), (uint8_t*)dataptr, NULL));
322 }
323 
324 uint8_t ACM::GetLineCoding(LINE_CODING *dataptr) {
325  return ( pUsb->ctrlReq(bAddress, 0, bmREQ_CDCIN, CDC_GET_LINE_CODING, 0x00, 0x00, bControlIface, sizeof (LINE_CODING), sizeof (LINE_CODING), (uint8_t*)dataptr, NULL));
326 }
327 
328 uint8_t ACM::SetControlLineState(uint8_t state) {
329  return ( pUsb->ctrlReq(bAddress, 0, bmREQ_CDCOUT, CDC_SET_CONTROL_LINE_STATE, state, 0, bControlIface, 0, 0, NULL, NULL));
330 }
331 
332 uint8_t ACM::SendBreak(uint16_t duration) {
333  return ( pUsb->ctrlReq(bAddress, 0, bmREQ_CDCOUT, CDC_SEND_BREAK, (duration & 0xff), (duration >> 8), bControlIface, 0, 0, NULL, NULL));
334 }
335 
337  Notify(PSTR("Endpoint descriptor:"), 0x80);
338  Notify(PSTR("\r\nLength:\t\t"), 0x80);
339  PrintHex<uint8_t > (ep_ptr->bLength, 0x80);
340  Notify(PSTR("\r\nType:\t\t"), 0x80);
341  PrintHex<uint8_t > (ep_ptr->bDescriptorType, 0x80);
342  Notify(PSTR("\r\nAddress:\t"), 0x80);
343  PrintHex<uint8_t > (ep_ptr->bEndpointAddress, 0x80);
344  Notify(PSTR("\r\nAttributes:\t"), 0x80);
345  PrintHex<uint8_t > (ep_ptr->bmAttributes, 0x80);
346  Notify(PSTR("\r\nMaxPktSize:\t"), 0x80);
347  PrintHex<uint16_t > (ep_ptr->wMaxPacketSize, 0x80);
348  Notify(PSTR("\r\nPoll Intrv:\t"), 0x80);
349  PrintHex<uint8_t > (ep_ptr->bInterval, 0x80);
350  Notify(PSTR("\r\n"), 0x80);
351 }
#define USB_CLASS_COM_AND_CDC_CTRL
Definition: UsbCore.h:56
#define USB_CLASS_CDC_DATA
Definition: UsbCore.h:63
uint8_t getConfDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t conf, uint8_t *dataptr)
Definition: Usb.cpp:766
#define CDC_SUBCLASS_ACM
Definition: cdcacm.h:27
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:81
static const uint8_t epInterruptInIndex
Definition: cdcacm.h:142
uint8_t bmNakPower
Definition: address.h:42
static const uint8_t epDataOutIndex
Definition: cdcacm.h:141
#define CDC_CLEAR_COMM_FEATURE
Definition: cdcacm.h:55
uint32_t qNextPollTime
Definition: cdcacm.h:151
uint8_t bControlIface
Definition: cdcacm.h:148
#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
bool ready
Definition: cdcacm.h:153
#define NotifyFail(...)
Definition: message.h:55
uint8_t bDataIface
Definition: cdcacm.h:149
USB * pUsb
Definition: cdcacm.h:144
uint8_t setConf(uint8_t addr, uint8_t ep, uint8_t conf_value)
Definition: Usb.cpp:805
uint8_t bNumEP
Definition: cdcacm.h:150
#define bmREQ_CDCOUT
Definition: cdcacm.h:22
EpInfo epInfo[ACM_MAX_ENDPOINTS]
Definition: cdcacm.h:155
#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
bool bPollEnable
Definition: cdcacm.h:152
#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:336
#define Notify(...)
Definition: message.h:44
CDCAsyncOper * pAsync
Definition: cdcacm.h:145
#define USBTRACE2(s, r)
Definition: macros.h:77
uint8_t setAddr(uint8_t oldaddr, uint8_t ep, uint8_t newaddr)
Definition: Usb.cpp:796
#define ACM_MAX_ENDPOINTS
Definition: cdcacm.h:136
#define NotifyFailGetConfDescr(...)
Definition: message.h:52
uint8_t GetLineCoding(LINE_CODING *dataptr)
Definition: cdcacm.cpp:324
uint8_t epAddr
Definition: address.h:33
#define USB_NAK_MAX_POWER
Definition: address.h:27
#define bmREQ_CDCIN
Definition: cdcacm.h:23
uint8_t SndData(uint16_t nbytes, uint8_t *dataptr)
Definition: cdcacm.cpp:304
virtual uint8_t Poll()
Definition: cdcacm.cpp:264
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
virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed)
Definition: cdcacm.cpp:47
#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:140
uint8_t bAddress
Definition: cdcacm.h:146
#define USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE
Definition: UsbCore.h:83
uint8_t SetLineCoding(const LINE_CODING *dataptr)
Definition: cdcacm.cpp:320
virtual void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep)
Definition: cdcacm.cpp:224
uint8_t SendBreak(uint16_t duration)
Definition: cdcacm.cpp:332
#define USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL
Definition: UsbCore.h:80
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:75
uint8_t GetCommFeature(uint16_t fid, uint8_t nbytes, uint8_t *dataptr)
Definition: cdcacm.cpp:312
virtual uint8_t Release()
Definition: cdcacm.cpp:251
uint8_t bConfNum
Definition: cdcacm.h:147
uint8_t bNumConfigurations
Definition: usb_ch9.h:112
#define USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL
Definition: UsbCore.h:78
#define CDC_SET_CONTROL_LINE_STATE
Definition: cdcacm.h:64
virtual uint8_t OnInit(ACM *pacm)=0
uint8_t maxPktSize
Definition: address.h:34
AddressPool & GetAddressPool()
Definition: UsbCore.h:206
Definition: UsbCore.h:190
uint8_t RegisterDeviceClass(USBDeviceConfig *pdev)
Definition: UsbCore.h:210
#define NotifyFailSetConfDescr(...)
Definition: message.h:53
uint8_t SetControlLineState(uint8_t state)
Definition: cdcacm.cpp:328
uint8_t SetCommFeature(uint16_t fid, uint8_t nbytes, uint8_t *dataptr)
Definition: cdcacm.cpp:308
uint8_t ClearCommFeature(uint16_t fid)
Definition: cdcacm.cpp:316
#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:761
#define NotifyFailSetDevTblEntry(...)
Definition: message.h:51
uint8_t RcvData(uint16_t *nbytesptr, uint8_t *dataptr)
Definition: cdcacm.cpp:300