source: rtos_arduino/trunk/arduino_lib/libraries/USBHost/src/address.h@ 136

Last change on this file since 136 was 136, checked in by ertl-honda, 8 years ago

ライブラリとOS及びベーシックなサンプルの追加.

File size: 10.2 KB
Line 
1/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved.
2
3This software may be distributed and modified under the terms of the GNU
4General Public License version 2 (GPL2) as published by the Free Software
5Foundation and appearing in the file GPL2.TXT included in the packaging of
6this file. Please note that GPL2 Section 2[b] requires that all works based
7on this software must also be made publicly available under the terms of
8the GPL2 ("Copyleft").
9
10Contact information
11-------------------
12
13Circuits At Home, LTD
14Web : http://www.circuitsathome.com
15e-mail : support@circuitsathome.com
16*/
17
18#ifndef ADDRESS_H_INCLUDED
19#define ADDRESS_H_INCLUDED
20
21#include <stdint.h>
22
23/* NAK powers. To save space in endpoint data structure, amount of retries before giving up and returning 0x4 is stored in */
24/* bmNakPower as a power of 2. The actual nak_limit is then calculated as nak_limit = ( 2^bmNakPower - 1) */
25#define USB_NAK_MAX_POWER 16 //NAK binary order maximum value
26#define USB_NAK_DEFAULT 14 //default 16K-1 NAKs before giving up
27#define USB_NAK_NOWAIT 1 //Single NAK stops transfer
28#define USB_NAK_NONAK 0 //Do not count NAKs, stop retrying after USB Timeout
29
30/**
31 * \brief Device endpoint definition.
32 *
33 * \note hostPipeNum is the allocated pipe used for the communication with
34 * deviceEpNum remote device endpoint.
35 * There is exactly one hostPipeNum corresponding to a deviceEpNum.
36 *
37 * \note The number of host pipe is limited by the hardware (10 on SAM3X).
38 * Moreover hostPipeNum allocation is static, meaning that only a limited
39 * amount of device endpoints can be opened at the same time, thus limitating
40 * the maximum number of connected devices at the same time.
41 */
42struct EpInfo
43{
44 uint32_t deviceEpNum; // Device endpoint number
45 uint32_t hostPipeNum; // Host corresponding pipe number
46 uint32_t maxPktSize; // Maximum packet size
47
48 union
49 {
50 uint8_t epAttribs;
51
52 struct
53 {
54 uint8_t bmSndToggle : 1; // Send toggle, when zero bmSNDTOG0, bmSNDTOG1 otherwise
55 uint8_t bmRcvToggle : 1; // Send toggle, when zero bmRCVTOG0, bmRCVTOG1 otherwise
56 uint8_t bmNakPower : 6; // Binary order for NAK_LIMIT value
57 };
58 };
59};
60
61/**
62 * \brief USB device address definition.
63 *
64 * \note The 8 bits USB address is defined like this:
65 *
66 * 7 6 5 4 3 2 1 0
67 * ---------------------------------
68 * | | H | P | P | P | A | A | A |
69 * ---------------------------------
70 *
71 * H - if 1 the address is a hub address
72 * P - parent hub address
73 * A - device address / port number in case of hub
74 */
75struct UsbDeviceAddress
76{
77 union
78 {
79 struct
80 {
81 uint32_t bmAddress : 3; // device address/port number
82 uint32_t bmParent : 3; // parent hub address
83 uint32_t bmHub : 1; // hub flag
84 uint32_t bmReserved : 25; // reserved, must be zerro
85 };
86 uint32_t devAddress;
87 };
88};
89
90#define bmUSB_DEV_ADDR_ADDRESS 0x07
91#define bmUSB_DEV_ADDR_PARENT 0x38
92#define bmUSB_DEV_ADDR_HUB 0x40
93
94/**
95 * \brief USB device definition.
96 *
97 * \note epinfo is used to store the list of device endpoints currently used
98 * by the USBHost stack. This field is set during enumeration process when
99 * a supported USB class is found. See any USB classes implementing
100 * USBDeviceConfig and init() method for reference.
101 */
102struct UsbDevice
103{
104 EpInfo *epinfo; // endpoint info pointer
105 uint32_t address; // address
106 uint32_t epcount; // number of endpoints
107 uint32_t lowspeed; // indicates if a device is the low speed one
108};
109
110/**
111 * \class Abstract AddressPool definition.
112 */
113class AddressPool
114{
115public:
116 virtual UsbDevice* GetUsbDevicePtr(uint32_t addr) = 0;
117 virtual uint32_t AllocAddress(uint32_t parent, uint32_t is_hub = 0, uint32_t port = 0) = 0;
118 virtual void FreeAddress(uint32_t addr) = 0;
119};
120
121typedef void (*UsbDeviceHandleFunc)(UsbDevice *pdev);
122
123#define ADDR_ERROR_INVALID_INDEX 0xFF
124#define ADDR_ERROR_INVALID_ADDRESS 0xFF
125
126/**
127 * \class AddressPoolImpl definition.
128 * Used to store the list of connected devices and to keep track of free USB
129 * addresses.
130 */
131template <const uint32_t MAX_DEVICES_ALLOWED>
132class AddressPoolImpl : public AddressPool
133{
134private:
135
136 EpInfo dev0ep; // Endpoint data structure used during enumeration for uninitialized device
137
138 uint32_t hubCounter; // hub counter is kept
139 // in order to avoid hub address duplication
140
141 UsbDevice thePool[MAX_DEVICES_ALLOWED];
142
143 /**
144 * \brief Initialize the specified address pool entry.
145 *
146 * \param index Index pointing to a UsbDevice instance in the address pool.
147 */
148 void InitEntry(uint32_t index)
149 {
150 thePool[index].address = 0;
151 thePool[index].epcount = 1;
152 thePool[index].lowspeed = 0;
153 thePool[index].epinfo = &dev0ep;
154 };
155
156 /**
157 * \brief Return an address pool index for a given address. This index can
158 * further be used to retrieve the corresponding USB device instance
159 * UsbDevice.
160 *
161 * \param index Index pointing to a UsbDevice instance in the address pool.
162 *
163 * \return Index number if found, 0 otherwise.
164 * \note Index 0 is reserved for address 0 and shall never be used.
165 */
166 uint32_t FindAddressIndex(uint32_t address = 0)
167 {
168 for (uint8_t i = 1; i < MAX_DEVICES_ALLOWED; i++)
169 {
170 if (thePool[i].address == address)
171 return i;
172 }
173 return 0;
174 };
175
176 /**
177 * \brief Return address pool child index for a given parent. This index can
178 * further be used to retrieve the corresponding USB device instance
179 * UsbDevice.
180 *
181 * \param addr Parent USB address.
182 * \param start Search in the pool from this index. Calling multiple time
183 * this function with the returned index + 1 can be used to walk through
184 * all children.
185 *
186 * \return Child index number if found, 0 otherwise.
187 * \note Index 0 is reserved for address 0 and shall never be used.
188 */
189 uint32_t FindChildIndex(UsbDeviceAddress addr, uint32_t start = 1)
190 {
191 for (uint32_t i = (start < 1 || start >= MAX_DEVICES_ALLOWED) ? 1 : start; i < MAX_DEVICES_ALLOWED; ++i)
192 {
193 if (((UsbDeviceAddress*)&thePool[i].address)->bmParent == addr.bmAddress)
194 return i;
195 }
196
197 return 0;
198 };
199
200 /**
201 * \brief Free address entry specified by index parameter.
202 *
203 * \note Calling FreeAddressByIndex only frees the USB address for possible
204 * further assignement. However, it does not free the actual USB resources
205 * used by the device. This can be made by calling the release() method
206 * from any UsbDevice class implementing USBDeviceConfig.
207 *
208 * \param index Index pointing to a UsbDevice instance in the address pool.
209 *
210 * \note Calling FreeAddressByIndex with a 0 index param has no effect.
211 */
212 void FreeAddressByIndex(uint32_t index)
213 {
214 // Zero field is reserved and should not be affected
215 if (index == 0)
216 return;
217
218 // If a hub was switched off all port addresses should be freed
219 if (((UsbDeviceAddress*)&thePool[index].address)->bmHub == 1)
220 {
221 for (uint32_t i = 1; (i = FindChildIndex(*((UsbDeviceAddress*)&thePool[index].address), i) > 0); )
222 FreeAddressByIndex(i);
223
224 // If the hub had the last allocated address, hubCounter should be decremented
225 if (hubCounter == ((UsbDeviceAddress*)&thePool[index].address)->bmAddress)
226 hubCounter --;
227 }
228
229 InitEntry(index);
230 }
231
232 /**
233 * \brief Initialize all address poll entries at once.
234 */
235 void InitAllAddresses()
236 {
237 for (uint32_t i = 1; i < MAX_DEVICES_ALLOWED; i++)
238 InitEntry(i);
239
240 hubCounter = 0;
241 };
242
243public:
244 /**
245 * \brief AddressPoolImpl class constructor.
246 */
247 AddressPoolImpl() : hubCounter(0)
248 {
249 // Init address zero (reserved)
250 InitEntry(0);
251
252 // Init all remaing addresses
253 InitAllAddresses();
254
255 // Configure ep0 used for enumeration
256 dev0ep.deviceEpNum = 0;
257 dev0ep.hostPipeNum = 0;
258 dev0ep.maxPktSize = 8;
259 };
260
261 /**
262 * \brief Get a UsbDevice pointer from a USB device address.
263 *
264 * \param addr USB device address.
265 *
266 * \return UsbDevice pointer on success, 0 otherwise.
267 */
268 virtual UsbDevice* GetUsbDevicePtr(uint32_t addr)
269 {
270 if (!addr)
271 return thePool;
272
273 uint32_t index = FindAddressIndex(addr);
274
275 return (!index) ? 0 : (thePool + index);
276 };
277
278 /**
279 * \brief Perform an operation specified by pfunc for each addressed
280 * USB device.
281 *
282 * \param pfunc Any function pointer with type UsbDeviceHandleFunc.
283 */
284 void ForEachUsbDevice(UsbDeviceHandleFunc pfunc)
285 {
286 if (!pfunc)
287 return;
288
289 for (uint32_t i = 1; i < MAX_DEVICES_ALLOWED; i++)
290 if (thePool[i].address)
291 pfunc(thePool + i);
292 };
293
294 /**
295 * \brief Allocate a new USB device address.
296 *
297 * \note See UsbDeviceAddress definition for better understanding.
298 *
299 * \param parent USB device address of the Parent device.
300 * \param is_hub Set to true if the corresponding device is a Hub, false
301 * otherwise.
302 * \param port USB device base address.
303 *
304 * \return UsbDevice pointer on success, 0 otherwise.
305 */
306 virtual uint32_t AllocAddress(uint32_t parent, uint32_t is_hub = 0, uint32_t port = 0)
307 {
308 if (parent > 127 || port > 7)
309 return 0;
310
311 if (is_hub && hubCounter == 7)
312 return 0;
313
314 // Finds first empty address entry starting from one
315 uint32_t index = FindAddressIndex(0);
316
317 // If empty entry is not found
318 if (!index)
319 return 0;
320
321 if (parent == 0)
322 {
323 if (is_hub)
324 {
325 thePool[index].address = 0x41;
326 hubCounter++;
327 }
328 else
329 thePool[index].address = 1;
330
331 return thePool[index].address;
332 }
333
334 UsbDeviceAddress addr;
335
336 addr.bmParent = ((UsbDeviceAddress*)&parent)->bmAddress;
337
338 if (is_hub)
339 {
340 addr.bmHub = 1;
341 addr.bmAddress = hubCounter++;
342 }
343 else
344 {
345 addr.bmHub = 0;
346 addr.bmAddress = port;
347 }
348
349 thePool[index].address = *((uint8_t*)&addr);
350
351 return thePool[index].address;
352 };
353
354 /**
355 * \brief Free the specified USB device address.
356 *
357 * \param addr USB device address to free.
358 */
359 virtual void FreeAddress(uint32_t addr)
360 {
361 // If the root hub is disconnected all the addresses should be initialized
362 if (addr == 0x41)
363 {
364 InitAllAddresses();
365 return;
366 }
367
368 uint32_t index = FindAddressIndex(addr);
369 FreeAddressByIndex(index);
370 };
371
372 // Returns number of hubs attached
373 // It can be rather helpfull to find out if there are hubs attached than getting the exact number of hubs.
374 /*uint32_t GetNumHubs()
375 {
376 return hubCounter;
377 };
378
379 uint32_t GetNumDevices()
380 {
381 uint32_t counter = 0;
382
383 for (uint32_t i = 1; i < MAX_DEVICES_ALLOWED; ++i)
384 if (thePool[i].address != 0);
385 counter++;
386
387 return counter;
388 };*/
389
390};
391
392#endif /* ADDRESS_H_INCLUDED */
Note: See TracBrowser for help on using the repository browser.