Prusa MINI Firmware overview
address.h
Go to the documentation of this file.
1 /**
2  * Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * Contact information
19  * -------------------
20  *
21  * Circuits At Home, LTD
22  * Web : http://www.circuitsathome.com
23  * e-mail : support@circuitsathome.com
24  */
25 #pragma once
26 
27 #ifndef _usb_h_
28  #error "Never include address.h directly; include Usb.h instead"
29 #endif
30 
31 /* NAK powers. To save space in endpoint data structure, amount of retries before giving up and returning 0x4 is stored in */
32 /* bmNakPower as a power of 2. The actual nak_limit is then calculated as nak_limit = ( 2^bmNakPower - 1) */
33 #define USB_NAK_MAX_POWER 15 //NAK binary order maximum value
34 #define USB_NAK_DEFAULT 14 //default 32K-1 NAKs before giving up
35 #define USB_NAK_NOWAIT 1 //Single NAK stops transfer
36 #define USB_NAK_NONAK 0 //Do not count NAKs, stop retrying after USB Timeout
37 
38 struct EpInfo {
39  uint8_t epAddr; // Endpoint address
40  uint8_t maxPktSize; // Maximum packet size
41 
42  union {
44 
45  struct {
46  uint8_t bmSndToggle : 1; // Send toggle, when zero bmSNDTOG0, bmSNDTOG1 otherwise
47  uint8_t bmRcvToggle : 1; // Send toggle, when zero bmRCVTOG0, bmRCVTOG1 otherwise
48  uint8_t bmNakPower : 6; // Binary order for NAK_LIMIT value
49  } __attribute__((packed));
50  };
51 } __attribute__((packed));
52 
53 // 7 6 5 4 3 2 1 0
54 // ---------------------------------
55 // | | H | P | P | P | A | A | A |
56 // ---------------------------------
57 //
58 // H - if 1 the address is a hub address
59 // P - parent hub address
60 // A - device address / port number in case of hub
61 //
62 
64  union {
65  struct {
66  uint8_t bmAddress : 3; // device address/port number
67  uint8_t bmParent : 3; // parent hub address
68  uint8_t bmHub : 1; // hub flag
69  uint8_t bmReserved : 1; // reserved, must be zero
70  } __attribute__((packed));
72  };
73 } __attribute__((packed));
74 
75 #define bmUSB_DEV_ADDR_ADDRESS 0x07
76 #define bmUSB_DEV_ADDR_PARENT 0x38
77 #define bmUSB_DEV_ADDR_HUB 0x40
78 
79 struct UsbDevice {
80  EpInfo *epinfo; // endpoint info pointer
82  uint8_t epcount; // number of endpoints
83  bool lowspeed; // indicates if a device is the low speed one
84  // uint8_t devclass; // device class
85 } __attribute__((packed));
86 
87 class AddressPool {
88  public:
89  virtual UsbDevice* GetUsbDevicePtr(uint8_t addr) = 0;
90  virtual uint8_t AllocAddress(uint8_t parent, bool is_hub = false, uint8_t port = 0) = 0;
91  virtual void FreeAddress(uint8_t addr) = 0;
92 };
93 
95 
96 #define ADDR_ERROR_INVALID_INDEX 0xFF
97 #define ADDR_ERROR_INVALID_ADDRESS 0xFF
98 
99 template <const uint8_t MAX_DEVICES_ALLOWED>
100 class AddressPoolImpl : public AddressPool {
101  EpInfo dev0ep; //Endpoint data structure used during enumeration for uninitialized device
102 
103  uint8_t hubCounter; // hub counter is kept
104  // in order to avoid hub address duplication
105 
106  UsbDevice thePool[MAX_DEVICES_ALLOWED];
107 
108  // Initialize address pool entry
109 
110  void InitEntry(uint8_t index) {
111  thePool[index].address.devAddress = 0;
112  thePool[index].epcount = 1;
113  thePool[index].lowspeed = 0;
114  thePool[index].epinfo = &dev0ep;
115  }
116 
117  // Return thePool index for a given address
118 
119  uint8_t FindAddressIndex(uint8_t address = 0) {
120  for (uint8_t i = 1; i < MAX_DEVICES_ALLOWED; i++)
121  if (thePool[i].address.devAddress == address)
122  return i;
123 
124  return 0;
125  }
126 
127  // Return thePool child index for a given parent
128 
129  uint8_t FindChildIndex(UsbDeviceAddress addr, uint8_t start = 1) {
130  for (uint8_t i = (start < 1 || start >= MAX_DEVICES_ALLOWED) ? 1 : start; i < MAX_DEVICES_ALLOWED; i++) {
131  if (thePool[i].address.bmParent == addr.bmAddress)
132  return i;
133  }
134  return 0;
135  }
136 
137  // Frees address entry specified by index parameter
138 
139  void FreeAddressByIndex(uint8_t index) {
140  // Zero field is reserved and should not be affected
141  if (index == 0) return;
142 
143  UsbDeviceAddress uda = thePool[index].address;
144  // If a hub was switched off all port addresses should be freed
145  if (uda.bmHub == 1) {
146  for (uint8_t i = 1; (i = FindChildIndex(uda, i));)
147  FreeAddressByIndex(i);
148 
149  // If the hub had the last allocated address, hubCounter should be decremented
150  if (hubCounter == uda.bmAddress) hubCounter--;
151  }
152  InitEntry(index);
153  }
154 
155  // Initialize the whole address pool at once
156 
157  void InitAllAddresses() {
158  for (uint8_t i = 1; i < MAX_DEVICES_ALLOWED; i++)
159  InitEntry(i);
160 
161  hubCounter = 0;
162  }
163 
164 public:
165 
166  AddressPoolImpl() : hubCounter(0) {
167  // Zero address is reserved
168  InitEntry(0);
169 
170  thePool[0].address.devAddress = 0;
171  thePool[0].epinfo = &dev0ep;
172  dev0ep.epAddr = 0;
173  dev0ep.maxPktSize = 8;
174  dev0ep.bmSndToggle = 0; // Set DATA0/1 toggles to 0
175  dev0ep.bmRcvToggle = 0;
176  dev0ep.bmNakPower = USB_NAK_MAX_POWER;
177 
178  InitAllAddresses();
179  }
180 
181  // Return a pointer to a specified address entry
182 
184  if (!addr) return thePool;
185  uint8_t index = FindAddressIndex(addr);
186  return index ? thePool + index : nullptr;
187  }
188 
189  // Perform an operation specified by pfunc for each addressed device
190 
192  if (pfunc) {
193  for (uint8_t i = 1; i < MAX_DEVICES_ALLOWED; i++)
194  if (thePool[i].address.devAddress)
195  pfunc(thePool + i);
196  }
197  }
198 
199  // Allocate new address
200 
201  virtual uint8_t AllocAddress(uint8_t parent, bool is_hub = false, uint8_t port = 0) {
202  /* if (parent != 0 && port == 0)
203  USB_HOST_SERIAL.println("PRT:0"); */
205  _parent.devAddress = parent;
206  if (_parent.bmReserved || port > 7)
207  //if(parent > 127 || port > 7)
208  return 0;
209 
210  if (is_hub && hubCounter == 7) return 0;
211 
212  // finds first empty address entry starting from one
213  uint8_t index = FindAddressIndex(0);
214 
215  if (!index) return 0; // if empty entry is not found
216 
217  if (_parent.devAddress == 0) {
218  if (is_hub) {
219  thePool[index].address.devAddress = 0x41;
220  hubCounter++;
221  }
222  else
223  thePool[index].address.devAddress = 1;
224 
225  return thePool[index].address.devAddress;
226  }
227 
228  UsbDeviceAddress addr;
229  addr.devAddress = 0; // Ensure all bits are zero
230  addr.bmParent = _parent.bmAddress;
231  if (is_hub) {
232  addr.bmHub = 1;
233  addr.bmAddress = ++hubCounter;
234  }
235  else {
236  addr.bmHub = 0;
237  addr.bmAddress = port;
238  }
239  thePool[index].address = addr;
240  /*
241  USB_HOST_SERIAL.print("Addr:");
242  USB_HOST_SERIAL.print(addr.bmHub, HEX);
243  USB_HOST_SERIAL.print(".");
244  USB_HOST_SERIAL.print(addr.bmParent, HEX);
245  USB_HOST_SERIAL.print(".");
246  USB_HOST_SERIAL.println(addr.bmAddress, HEX);
247  */
248  return thePool[index].address.devAddress;
249  }
250 
251  // Empty the pool entry
252 
253  virtual void FreeAddress(uint8_t addr) {
254  // if the root hub is disconnected all the addresses should be initialized
255  if (addr == 0x41) {
256  InitAllAddresses();
257  return;
258  }
259  FreeAddressByIndex(FindAddressIndex(addr));
260  }
261 
262  // Return number of hubs attached
263  // It can be helpful to find out if hubs are attached when getting the exact number of hubs.
264  //uint8_t GetNumHubs() { return hubCounter; }
265  //uint8_t GetNumDevices() {
266  // uint8_t counter = 0;
267  // for (uint8_t i = 1; i < MAX_DEVICES_ALLOWED; i++)
268  // if (thePool[i].address != 0); counter++;
269  // return counter;
270  //}
271 };
AddressPool::GetUsbDevicePtr
virtual UsbDevice * GetUsbDevicePtr(uint8_t addr)=0
AddressPool
Definition: address.h:87
EpInfo::bmSndToggle
uint8_t bmSndToggle
Definition: address.h:46
AddressPoolImpl
Definition: address.h:100
UsbDevice::lowspeed
bool lowspeed
Definition: address.h:83
AddressPool::AllocAddress
virtual uint8_t AllocAddress(uint8_t parent, bool is_hub=false, uint8_t port=0)=0
UsbDeviceAddress::bmReserved
uint8_t bmReserved
Definition: address.h:69
g29_auto.start
start
Definition: g29_auto.py:150
i
uint8_t i
Definition: screen_test_graph.c:72
EpInfo::epAddr
uint8_t epAddr
Definition: address.h:39
UsbDeviceAddress
Definition: address.h:63
AddressPoolImpl::ForEachUsbDevice
void ForEachUsbDevice(UsbDeviceHandleFunc pfunc)
Definition: address.h:191
EpInfo::bmNakPower
uint8_t bmNakPower
Definition: address.h:48
AddressPoolImpl::FreeAddress
virtual void FreeAddress(uint8_t addr)
Definition: address.h:253
UsbDeviceAddress::devAddress
uint8_t devAddress
Definition: address.h:71
USB_NAK_MAX_POWER
#define USB_NAK_MAX_POWER
Definition: address.h:33
UsbDeviceAddress::bmParent
uint8_t bmParent
Definition: address.h:67
UsbDeviceAddress::__attribute__
union UsbDeviceAddress::@30 __attribute__
EpInfo
Definition: address.h:38
void
void
Definition: png.h:1083
EpInfo::bmRcvToggle
uint8_t bmRcvToggle
Definition: address.h:47
AddressPoolImpl::AddressPoolImpl
AddressPoolImpl()
Definition: address.h:166
AddressPoolImpl::AllocAddress
virtual uint8_t AllocAddress(uint8_t parent, bool is_hub=false, uint8_t port=0)
Definition: address.h:201
AddressPoolImpl::GetUsbDevicePtr
virtual UsbDevice * GetUsbDevicePtr(uint8_t addr)
Definition: address.h:183
EpInfo::epAttribs
uint8_t epAttribs
Definition: address.h:43
UsbDevice::epcount
uint8_t epcount
Definition: address.h:82
UsbDevice::address
UsbDeviceAddress address
Definition: address.h:81
uint8_t
const uint8_t[]
Definition: 404_html.c:3
address
UsbDeviceAddress address
Definition: address.h:202
UsbDevice
Definition: address.h:79
__attribute__
union @28 __attribute__
UsbDeviceHandleFunc
void(* UsbDeviceHandleFunc)(UsbDevice *pdev)
Definition: address.h:94
AddressPool::FreeAddress
virtual void FreeAddress(uint8_t addr)=0
EpInfo::maxPktSize
uint8_t maxPktSize
Definition: address.h:40
UsbDeviceAddress::bmAddress
uint8_t bmAddress
Definition: address.h:66
UsbDeviceAddress::bmHub
uint8_t bmHub
Definition: address.h:68
UsbDevice::epinfo
EpInfo * epinfo
Definition: address.h:80