USB Host Shield 2.0
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
cdcftdi.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 "cdcftdi.h"
18 
19 const uint8_t FTDI::epDataInIndex = 1;
20 const uint8_t FTDI::epDataOutIndex = 2;
21 const uint8_t FTDI::epInterruptInIndex = 3;
22 
24 pAsync(pasync),
25 pUsb(p),
26 bAddress(0),
27 bNumEP(1),
28 wFTDIType(0) {
29  for(uint8_t i = 0; i < FTDI_MAX_ENDPOINTS; i++) {
30  epInfo[i].epAddr = 0;
31  epInfo[i].maxPktSize = (i) ? 0 : 8;
32  epInfo[i].epAttribs = 0;
33 
34  //if (!i)
35  epInfo[i].bmNakPower = USB_NAK_MAX_POWER;
36  }
37  if(pUsb)
38  pUsb->RegisterDeviceClass(this);
39 }
40 
41 uint8_t FTDI::Init(uint8_t parent, uint8_t port, bool lowspeed) {
42  const uint8_t constBufSize = sizeof (USB_DEVICE_DESCRIPTOR);
43 
44  uint8_t buf[constBufSize];
45  USB_DEVICE_DESCRIPTOR * udd = reinterpret_cast<USB_DEVICE_DESCRIPTOR*>(buf);
46  uint8_t rcode;
47  UsbDevice *p = NULL;
48  EpInfo *oldep_ptr = NULL;
49  //uint8_t len = 0;
50  //uint16_t cd_len = 0;
51 
52  uint8_t num_of_conf; // number of configurations
53  //uint8_t num_of_intf; // number of interfaces
54 
55  AddressPool &addrPool = pUsb->GetAddressPool();
56 
57  USBTRACE("FTDI Init\r\n");
58 
59  if(bAddress)
61 
62  // Get pointer to pseudo device with address 0 assigned
63  p = addrPool.GetUsbDevicePtr(0);
64 
65  if(!p)
67 
68  if(!p->epinfo) {
69  USBTRACE("epinfo\r\n");
71  }
72 
73  // Save old pointer to EP_RECORD of address 0
74  oldep_ptr = p->epinfo;
75 
76  // Temporary assign new pointer to epInfo to p->epinfo in order to avoid toggle inconsistence
77  p->epinfo = epInfo;
78 
79  p->lowspeed = lowspeed;
80 
81  // Get device descriptor
82  rcode = pUsb->getDevDescr(0, 0, sizeof (USB_DEVICE_DESCRIPTOR), buf);
83 
84  // Restore p->epinfo
85  p->epinfo = oldep_ptr;
86 
87  if(rcode)
88  goto FailGetDevDescr;
89  if(udd->idVendor != FTDI_VID || udd->idProduct != FTDI_PID)
91 
92  // Save type of FTDI chip
93  wFTDIType = udd->bcdDevice;
94 
95  // Allocate new address according to device class
96  bAddress = addrPool.AllocAddress(parent, false, port);
97 
98  if(!bAddress)
100 
101  // Extract Max Packet Size from the device descriptor
102  epInfo[0].maxPktSize = udd->bMaxPacketSize0;
103 
104  // Assign new address to the device
105  rcode = pUsb->setAddr(0, 0, bAddress);
106 
107  if(rcode) {
108  p->lowspeed = false;
109  addrPool.FreeAddress(bAddress);
110  bAddress = 0;
111  USBTRACE2("setAddr:", rcode);
112  return rcode;
113  }
114 
115  USBTRACE2("Addr:", bAddress);
116 
117  p->lowspeed = false;
118 
119  p = addrPool.GetUsbDevicePtr(bAddress);
120 
121  if(!p)
123 
124  p->lowspeed = lowspeed;
125 
126  num_of_conf = udd->bNumConfigurations;
127 
128  // Assign epInfo to epinfo pointer
129  rcode = pUsb->setEpInfoEntry(bAddress, 1, epInfo);
130 
131  if(rcode)
132  goto FailSetDevTblEntry;
133 
134  USBTRACE2("NC:", num_of_conf);
135 
136  for(uint8_t i = 0; i < num_of_conf; i++) {
139 
140  rcode = pUsb->getConfDescr(bAddress, 0, i, &HexDump);
141 
142  if(rcode)
143  goto FailGetConfDescr;
144 
145  rcode = pUsb->getConfDescr(bAddress, 0, i, &confDescrParser);
146 
147  if(rcode)
148  goto FailGetConfDescr;
149 
150  if(bNumEP > 1)
151  break;
152  } // for
153 
154  if(bNumEP < 2)
156 
157  USBTRACE2("NumEP:", bNumEP);
158 
159  // Assign epInfo to epinfo pointer
160  rcode = pUsb->setEpInfoEntry(bAddress, bNumEP, epInfo);
161 
162  USBTRACE2("Conf:", bConfNum);
163 
164  // Set Configuration Value
165  rcode = pUsb->setConf(bAddress, 0, bConfNum);
166 
167  if(rcode)
168  goto FailSetConfDescr;
169 
170  rcode = pAsync->OnInit(this);
171 
172  if(rcode)
173  goto FailOnInit;
174 
175  USBTRACE("FTDI configured\r\n");
176 
177  bPollEnable = true;
178  return 0;
179 
180 FailGetDevDescr:
181 #ifdef DEBUG_USB_HOST
183  goto Fail;
184 #endif
185 
186 FailSetDevTblEntry:
187 #ifdef DEBUG_USB_HOST
189  goto Fail;
190 #endif
191 
192 FailGetConfDescr:
193 #ifdef DEBUG_USB_HOST
195  goto Fail;
196 #endif
197 
198 FailSetConfDescr:
199 #ifdef DEBUG_USB_HOST
201  goto Fail;
202 #endif
203 
204 FailOnInit:
205 #ifdef DEBUG_USB_HOST
206  USBTRACE("OnInit:");
207 
208 Fail:
209  NotifyFail(rcode);
210 #endif
211  Release();
212  return rcode;
213 }
214 
215 void FTDI::EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *pep) {
216  ErrorMessage<uint8_t > (PSTR("Conf.Val"), conf);
217  ErrorMessage<uint8_t > (PSTR("Iface Num"), iface);
218  ErrorMessage<uint8_t > (PSTR("Alt.Set"), alt);
219 
220  bConfNum = conf;
221 
222  uint8_t index;
223 
224  if((pep->bmAttributes & 0x03) == 3 && (pep->bEndpointAddress & 0x80) == 0x80)
225  index = epInterruptInIndex;
226  else
227  if((pep->bmAttributes & 0x02) == 2)
228  index = ((pep->bEndpointAddress & 0x80) == 0x80) ? epDataInIndex : epDataOutIndex;
229  else
230  return;
231 
232  // Fill in the endpoint info structure
233  epInfo[index].epAddr = (pep->bEndpointAddress & 0x0F);
234  epInfo[index].maxPktSize = (uint8_t)pep->wMaxPacketSize;
235  epInfo[index].epAttribs = 0;
236 
237  bNumEP++;
238 
239  PrintEndpointDescriptor(pep);
240 }
241 
242 uint8_t FTDI::Release() {
243  pUsb->GetAddressPool().FreeAddress(bAddress);
244 
245  bAddress = 0;
246  bNumEP = 1;
247  qNextPollTime = 0;
248  bPollEnable = false;
249  return 0;
250 }
251 
252 uint8_t FTDI::Poll() {
253  uint8_t rcode = 0;
254 
255  //if (!bPollEnable)
256  // return 0;
257 
258  //if (qNextPollTime <= millis())
259  //{
260  // USB_HOST_SERIAL.println(bAddress, HEX);
261 
262  // qNextPollTime = millis() + 100;
263  //}
264  return rcode;
265 }
266 
267 uint8_t FTDI::SetBaudRate(uint32_t baud) {
268  uint16_t baud_value, baud_index = 0;
269  uint32_t divisor3;
270 
271  divisor3 = 48000000 / 2 / baud; // divisor shifted 3 bits to the left
272 
273  if(wFTDIType == FT232AM) {
274  if((divisor3 & 0x7) == 7)
275  divisor3++; // round x.7/8 up to x+1
276 
277  baud_value = divisor3 >> 3;
278  divisor3 &= 0x7;
279 
280  if(divisor3 == 1) baud_value |= 0xc000;
281  else // 0.125
282  if(divisor3 >= 4) baud_value |= 0x4000;
283  else // 0.5
284  if(divisor3 != 0) baud_value |= 0x8000; // 0.25
285  if(baud_value == 1) baud_value = 0; /* special case for maximum baud rate */
286  } else {
287  static const unsigned char divfrac [8] = {0, 3, 2, 0, 1, 1, 2, 3};
288  static const unsigned char divindex[8] = {0, 0, 0, 1, 0, 1, 1, 1};
289 
290  baud_value = divisor3 >> 3;
291  baud_value |= divfrac [divisor3 & 0x7] << 14;
292  baud_index = divindex[divisor3 & 0x7];
293 
294  /* Deal with special cases for highest baud rates. */
295  if(baud_value == 1) baud_value = 0;
296  else // 1.0
297  if(baud_value == 0x4001) baud_value = 1; // 1.5
298  }
299  USBTRACE2("baud_value:", baud_value);
300  USBTRACE2("baud_index:", baud_index);
301  return pUsb->ctrlReq(bAddress, 0, bmREQ_FTDI_OUT, FTDI_SIO_SET_BAUD_RATE, baud_value & 0xff, baud_value >> 8, baud_index, 0, 0, NULL, NULL);
302 }
303 
304 uint8_t FTDI::SetModemControl(uint16_t signal) {
305  return pUsb->ctrlReq(bAddress, 0, bmREQ_FTDI_OUT, FTDI_SIO_MODEM_CTRL, signal & 0xff, signal >> 8, 0, 0, 0, NULL, NULL);
306 }
307 
308 uint8_t FTDI::SetFlowControl(uint8_t protocol, uint8_t xon, uint8_t xoff) {
309  return pUsb->ctrlReq(bAddress, 0, bmREQ_FTDI_OUT, FTDI_SIO_SET_FLOW_CTRL, xon, xoff, protocol << 8, 0, 0, NULL, NULL);
310 }
311 
312 uint8_t FTDI::SetData(uint16_t databm) {
313  return pUsb->ctrlReq(bAddress, 0, bmREQ_FTDI_OUT, FTDI_SIO_SET_DATA, databm & 0xff, databm >> 8, 0, 0, 0, NULL, NULL);
314 }
315 
316 uint8_t FTDI::RcvData(uint16_t *bytes_rcvd, uint8_t *dataptr) {
317  return pUsb->inTransfer(bAddress, epInfo[epDataInIndex].epAddr, bytes_rcvd, dataptr);
318 }
319 
320 uint8_t FTDI::SndData(uint16_t nbytes, uint8_t *dataptr) {
321  return pUsb->outTransfer(bAddress, epInfo[epDataOutIndex].epAddr, nbytes, dataptr);
322 }
323 
324 void FTDI::PrintEndpointDescriptor(const USB_ENDPOINT_DESCRIPTOR* ep_ptr) {
325  Notify(PSTR("Endpoint descriptor:"), 0x80);
326  Notify(PSTR("\r\nLength:\t\t"), 0x80);
327  PrintHex<uint8_t > (ep_ptr->bLength, 0x80);
328  Notify(PSTR("\r\nType:\t\t"), 0x80);
329  PrintHex<uint8_t > (ep_ptr->bDescriptorType, 0x80);
330  Notify(PSTR("\r\nAddress:\t"), 0x80);
331  PrintHex<uint8_t > (ep_ptr->bEndpointAddress, 0x80);
332  Notify(PSTR("\r\nAttributes:\t"), 0x80);
333  PrintHex<uint8_t > (ep_ptr->bmAttributes, 0x80);
334  Notify(PSTR("\r\nMaxPktSize:\t"), 0x80);
335  PrintHex<uint16_t > (ep_ptr->wMaxPacketSize, 0x80);
336  Notify(PSTR("\r\nPoll Intrv:\t"), 0x80);
337  PrintHex<uint8_t > (ep_ptr->bInterval, 0x80);
338  Notify(PSTR("\r\n"), 0x80);
339 }
uint8_t getConfDescr(uint8_t addr, uint8_t ep, uint16_t nbytes, uint8_t conf, uint8_t *dataptr)
Definition: Usb.cpp:766
#define bmREQ_FTDI_OUT
Definition: cdcftdi.h:22
EpInfo * epinfo
Definition: address.h:76
virtual void EndpointXtract(uint8_t conf, uint8_t iface, uint8_t alt, uint8_t proto, const USB_ENDPOINT_DESCRIPTOR *ep)
Definition: cdcftdi.cpp:215
bool lowspeed
Definition: address.h:79
#define USB_ERROR_EPINFO_IS_NULL
Definition: UsbCore.h:81
uint8_t SetBaudRate(uint32_t baud)
Definition: cdcftdi.cpp:267
uint8_t bmNakPower
Definition: address.h:42
#define FT232AM
Definition: cdcftdi.h:31
uint16_t bcdDevice
Definition: usb_ch9.h:108
uint8_t SetModemControl(uint16_t control)
Definition: cdcftdi.cpp:304
#define FTDI_SIO_SET_BAUD_RATE
Definition: cdcftdi.h:40
uint8_t bMaxPacketSize0
Definition: usb_ch9.h:105
FTDI(USB *pusb, FTDIAsyncOper *pasync)
Definition: cdcftdi.cpp:23
#define NotifyFail(...)
Definition: message.h:55
#define FTDI_SIO_SET_DATA
Definition: cdcftdi.h:41
uint8_t SetFlowControl(uint8_t protocol, uint8_t xon=0x11, uint8_t xoff=0x13)
Definition: cdcftdi.cpp:308
uint8_t setConf(uint8_t addr, uint8_t ep, uint8_t conf_value)
Definition: Usb.cpp:805
#define NotifyFailGetDevDescr(...)
Definition: message.h:50
uint8_t setEpInfoEntry(uint8_t addr, uint8_t epcount, EpInfo *eprecord_ptr)
Definition: Usb.cpp:64
uint8_t RcvData(uint16_t *bytes_rcvd, uint8_t *dataptr)
Definition: cdcftdi.cpp:316
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
#define Notify(...)
Definition: message.h:44
#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 NotifyFailGetConfDescr(...)
Definition: message.h:52
uint8_t epAddr
Definition: address.h:33
#define USB_NAK_MAX_POWER
Definition: address.h:27
virtual uint8_t Poll()
Definition: cdcftdi.cpp:252
Definition: address.h:32
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
#define FTDI_PID
Definition: cdcftdi.h:29
virtual uint8_t Init(uint8_t parent, uint8_t port, bool lowspeed)
Definition: cdcftdi.cpp:41
#define FTDI_SIO_SET_FLOW_CTRL
Definition: cdcftdi.h:39
virtual uint8_t AllocAddress(uint8_t parent, bool is_hub=false, uint8_t port=0)=0
uint8_t bEndpointAddress
Definition: usb_ch9.h:144
#define USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE
Definition: UsbCore.h:83
uint8_t SndData(uint16_t nbytes, uint8_t *dataptr)
Definition: cdcftdi.cpp:320
virtual uint8_t OnInit(FTDI *pftdi)=0
#define USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL
Definition: UsbCore.h:80
#define FTDI_VID
Definition: cdcftdi.h:28
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
virtual uint8_t Release()
Definition: cdcftdi.cpp:242
uint16_t idProduct
Definition: usb_ch9.h:107
uint8_t bNumConfigurations
Definition: usb_ch9.h:112
#define USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL
Definition: UsbCore.h:78
#define FTDI_SIO_MODEM_CTRL
Definition: cdcftdi.h:38
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 SetData(uint16_t databm)
Definition: cdcftdi.cpp:312
#define FTDI_MAX_ENDPOINTS
Definition: cdcftdi.h:87
#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