1 #ifndef __USBH_X_DLIST_H__
2 #define __USBH_X_DLIST_H__
3
4 #include "USBH.h"
5 #include "USBH_Int.h"
6 #include <string.h>
7 #include <stdlib.h> // for atoi(), exit(), malloc(), free()
8 #include <stddef.h> // for offsetof()
9
10 #if (0)
11
12 // Double linked list structure. Can be used as either a list head, or as link words.
13
14 // @struct USBH_DLIST |
15 // The USBH_DLIST structure is the link element of the double linked list. It is used as either a list head, or as link entry.
16 // @field struct tDLIST * | Flink |
17 // Pointer to the successor (forward link).
18 // @field struct tDLIST * | pPrev |
19 // Pointer to the predecessor (backward link).
20 // @comm By means of such elements any structures may be handled as a double linked list. The USBH_DLIST structure is to be inserted
21 // into the structure which is to be handled. A pointer to the original structure can be obtained by means of the macro <f STRUCT_BASE_POINTER>.
22 typedef struct USBH_DLIST USBH_DLIST;
23 struct USBH_DLIST
24 {
25 USBH_DLIST * pNext;
26 USBH_DLIST * pPrev;
27 };
28
29 typedef struct USBH_DLIST_ITEM
30 {
31 struct USBH_DLIST_ITEM * pNext;
32 struct USBH_DLIST_ITEM * pPrev;
33 }USBH_DLIST_ITEM;
34
35 typedef struct
36 {
37 struct USBH_DLIST_ITEM * pFirst;
38 int NumItems;
39 }USBH_DLIST_HEAD;
40
41 #endif
42
43 #define offset_of_member( struct_name, member_name ) \
44 ( (unsigned int) (& ( (struct_name *) 0 ) -> member_name ) )
45
46 #define container_of(ptr, type, member) \
47 ( (type *)( (char *)ptr - offset_of_member(type,member) ) )
48
49 void USBH_DLIST_Init(USBH_DLIST * ListHead);
50 int USBH_DLIST_IsEmpty(USBH_DLIST * ListHead);
51 void USBH_DLIST_Append(USBH_DLIST * ListHead, USBH_DLIST * List);
52 void USBH_DLIST_InsertTail(USBH_DLIST * ListHead, USBH_DLIST * Entry);
53 void USBH_DLIST_InsertHead(USBH_DLIST * ListHead, USBH_DLIST * Entry);
54 void USBH_DLIST_InsertEntry(USBH_DLIST * Entry, USBH_DLIST * NewEntry);
55 void USBH_DLIST_RemoveTail(USBH_DLIST * ListHead, USBH_DLIST ** Entry);
56 void USBH_DLIST_RemoveHead(USBH_DLIST * ListHead, USBH_DLIST ** Entry);
57 void USBH_DLIST_RemoveEntry(USBH_DLIST * Entry);
58 USBH_DLIST * USBH_DLIST_GetPrev(USBH_DLIST * Entry);
59 USBH_DLIST * USBH_DLIST_GetNext(USBH_DLIST * Entry);
60
61 void USBH_DLIST_Add(USBH_DLIST_HEAD * pHead, USBH_DLIST_ITEM * pNew);
62 void USBH_DLIST_Remove(USBH_DLIST_HEAD * pHead, USBH_DLIST_ITEM * pItem);
63
64 //******************************************************************************
65 // Added
66 //******************************************************************************
67
68 typedef unsigned int (*NODE_MATCH_FUNC)(USBH_DLIST * Entry, void * pContext);
69
70 void USBH_X_DLIST_DeleteNode(USBH_DLIST * Entry, unsigned int EntryOffset);
71 void USBH_X_DLIST_DeleteAllNodes(USBH_DLIST * pHead, unsigned int EntryOffset);
72 void USBH_X_DLIST_DeleteMatchedNode(USBH_DLIST * pHead,
73 unsigned int EntryOffset, NODE_MATCH_FUNC NodeMacthFunc, void * pContext);
74 USBH_DLIST * USBH_X_DLIST_AddNode(USBH_DLIST * pHead,
75 unsigned int NodeEntryOffset, unsigned int NodeSize);
76
77 void USBH_X_DLIST_Test(void);
78
79 #endif /* __USBH_X_DLIST_H__ */
1 #include "USBH_X_Dlist.h"
2
3 #if (0)
4
5 void USBH_DLIST_Init(USBH_DLIST * ListHead);
6 int USBH_DLIST_IsEmpty(USBH_DLIST * ListHead);
7 void USBH_DLIST_Append(USBH_DLIST * ListHead, USBH_DLIST * List);
8 void USBH_DLIST_InsertTail(USBH_DLIST * ListHead, USBH_DLIST * Entry);
9 void USBH_DLIST_InsertHead(USBH_DLIST * ListHead, USBH_DLIST * Entry);
10 void USBH_DLIST_InsertEntry(USBH_DLIST * Entry, USBH_DLIST * NewEntry);
11 void USBH_DLIST_RemoveTail(USBH_DLIST * ListHead, USBH_DLIST ** Entry);
12 void USBH_DLIST_RemoveHead(USBH_DLIST * ListHead, USBH_DLIST ** Entry);
13 void USBH_DLIST_RemoveEntry(USBH_DLIST * Entry);
14 USBH_DLIST * USBH_DLIST_GetPrev(USBH_DLIST * Entry);
15 USBH_DLIST * USBH_DLIST_GetNext(USBH_DLIST * Entry);
16
17 /*********************************************************************
18 *
19 * USBH_DLIST
20 */
21
22 void USBH_DLIST_EmptyHead(USBH_DLIST_HEAD * pHead);
23 void USBH_DLIST_Add(USBH_DLIST_HEAD * pHead, USBH_DLIST_ITEM * pNew);
24 void USBH_DLIST_Remove(USBH_DLIST_HEAD * pHead, USBH_DLIST_ITEM * pItem);
25
26 // USBH_DLIST_Init
27 // STR R0, [R0,#4]
28 // STR R0, [R0]
29 // BX LR
30 void USBH_DLIST_Init(USBH_DLIST * ListHead)
31 {
32 ListHead->pPrev = ListHead;
33 ListHead->pNext = ListHead;
34 }
35
36 // USBH_DLIST_Append
37 // LDR R2, [R0,#4]
38 // STR R1, [R2]
39 // LDR R3, [R1,#4]
40 // STR R0, [R3]
41 // LDR R3, [R1,#4]
42 // STR R3, [R0,#4]
43 // STR R2, [R1,#4]
44 // BX LR
45
46 // /---<<<<<<<<<<<<<<<<<<<<<<pNext---\ /---<<<<<<<<<<<<<<<<<<pNext---\
47 // ListHead <----> 0 <----> 1 <----> N List <----> 0 <----> 1 <----> N
48 // pPrev >>>>>>>>>>>>>>>>>>>>>>>>>---/ pPrev >>>>>>>>>>>>>>>>>>>>>---/
49 //
50 // /---<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<pNext---\
51 // ListHead <----> 0 <----> 1 <----> N <----> List <----> 0 <----> 1 <----> N
52 // pPrev >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>---/
53 void USBH_DLIST_Append(USBH_DLIST * ListHead, USBH_DLIST * List)
54 {
55 ListHead->pPrev->pNext = List;
56 List->pPrev->pNext = ListHead;
57 ListHead->pPrev = List->pPrev;
58 List->pPrev = ListHead->pPrev;
59 }
60
61 // USBH_DLIST_IsEmpty
62 // LDR R1, [R0]
63 // CMP R1, R0
64 // ITE EQ
65 // MOVEQ R0, #1
66 // MOVNE R0, #0
67 // BX LR
68 int USBH_DLIST_IsEmpty(USBH_DLIST * ListHead)
69 {
70 return ListHead == ListHead->pNext;
71 }
72
73 // USBH_DLIST_GetNext USBH_DLIST_GetPrev
74 // LDR R0, [R0] LDR R0, [R0,#4]
75 // BX LR BX LR
76 USBH_DLIST * USBH_DLIST_GetNext(USBH_DLIST * Entry)
77 {
78 return Entry->pNext;
79 }
80 USBH_DLIST * USBH_DLIST_GetPrev(USBH_DLIST * Entry)
81 {
82 return Entry->pPrev;
83 }
84
85 // USBH_DLIST_RemoveHead USBH_DLIST_RemoveTail
86 // LDR R0, [R0] LDR R0, [R0,#4]
87 // USBH_DLIST_RemoveEntry STR R0, [R1] STR R0, [R1]
88 //
89 // LDRD.W R1, R2, [R0] LDRD.W R1, R2, [R0] LDRD.W R1, R2, [R0]
90 // STR R1, [R2] STR R1, [R2] STR R1, [R2]
91 //
92 // LDRD.W R1, R2, [R0] LDRD.W R1, R2, [R0] LDRD.W R1, R2, [R0]
93 // STR R2, [R1,#4] STR R2, [R1,#4] STR R2, [R1,#4]
94 //
95 // STR R0, [R0,#4] STR R0, [R0,#4] STR R0, [R0,#4]
96 // STR R0, [R0] STR R0, [R0] STR R0, [R0]
97 // BX LR BX LR BX LR
98
99 // pPrev [ Entry ] pNext ---> pPrev pNext
100 void USBH_DLIST_RemoveEntry(USBH_DLIST * Entry)
101 {
102 Entry->pPrev->pNext = Entry->pNext;
103 Entry->pNext->pPrev = Entry->pPrev;
104 //USBH_DLIST_Init( Entry );
105 Entry->pPrev = Entry;
106 Entry->pNext = Entry;
107 }
108
109 void USBH_DLIST_RemoveHead(USBH_DLIST * ListHead, USBH_DLIST ** Entry)
110 {
111 ( *Entry )->pNext = ListHead->pNext;
112 USBH_DLIST_RemoveEntry( ListHead->pNext );
113 }
114
115 void USBH_DLIST_RemoveTail(USBH_DLIST * ListHead, USBH_DLIST ** Entry)
116 {
117 ( *Entry )->pNext = ListHead->pPrev;
118 USBH_DLIST_RemoveEntry( ListHead->pPrev );
119 }
120
121 // USBH_DLIST_InsertTail
122 // USBH_DLIST_InsertEntry USBH_DLIST_InsertHead LDR R0, [R0,#4]
123 // LDR R2, [R0] LDR R2, [R0] LDR R2, [R0]
124 // STRD.W R2, R0, [R1] STRD.W R2, R0, [R1] STRD.W R2, R0, [R1]
125 // LDR R2, [R0] LDR R2, [R0] LDR R2, [R0]
126 // STR R1, [R2,#4] STR R1, [R2,#4] STR R1, [R2,#4]
127 // STR R1, [R0] STR R1, [R0] STR R1, [R0]
128 // BX LR BX LR BX LR
129
130 void USBH_DLIST_InsertEntry(USBH_DLIST * Entry, USBH_DLIST * NewEntry)
131 {
132 NewEntry->pNext = Entry->pNext;
133 NewEntry->pPrev = Entry;
134
135 Entry->pNext->pPrev = NewEntry;
136 Entry->pNext = NewEntry;
137 }
138
139 void USBH_DLIST_InsertHead(USBH_DLIST * ListHead, USBH_DLIST * Entry)
140 {
141 USBH_DLIST_InsertEntry( ListHead, Entry );
142 }
143
144 void USBH_DLIST_InsertTail(USBH_DLIST * ListHead, USBH_DLIST * Entry)
145 {
146 USBH_DLIST_InsertEntry( ListHead->pPrev, Entry );
147 }
148
149 // USBH_DLIST_Add
150 // MOVS R2, #0
151 // STR R2, [R1,#4] ; pNew->pPrev = 0;
152 //
153 // LDR R2, [R0]
154 // STR R2, [R1] ; pNew->pNext = pHead->pFirst;
155 //
156 // LDR R2, [R0]
157 // CMP R2, #0
158 // IT NE ; pHead->pFirst != 0
159 // STRNE R1, [R2,#4] ; pHead->pFirst->pPrev = pNew;
160 //
161 // STR R1, [R0] ; pHead->pFirst = pNew;
162 // BX LR
163 //
164 // pFirst --> pNew
165 // 0 <------- pNew ----> 0
166 //
167 // 0 <------- pNew ----> pOld
168 // pNew <---- pOld ----> 0
169 //
170 // 0 <-------\____
171 // pFirst --> pNew <----> pOld <----> pOld <----> pOld ----> 0
172 void USBH_DLIST_Add(USBH_DLIST_HEAD * pHead, USBH_DLIST_ITEM * pNew)
173 {
174 pNew->pPrev = 0;
175 pNew->pNext = 0; // (pHead->pFirst == 0)
176 if (pHead->pFirst != 0)
177 {
178 pNew->pNext = pHead->pFirst;
179 pHead->pFirst->pPrev = pNew;
180 }
181 pHead->pFirst = pNew;
182 //pHead->NumItems++;
183 }
184
185 // USBH_DLIST_Remove
186 // LDR R3, [R0]
187 // LDR R2, [R1]
188 //
189 // CMP R3, R1
190 // IT NE
191 // LDRNE R0, [R1,#4]
192 // STR R2, [R0]
193 //
194 // LDR R0, [R1]
195 // CMP R0, #0
196 // ITT NE
197 // LDRNE R1, [R1,#4]
198 // STRNE R1, [R0,#4]
199 //
200 // BX LR
201 //
202 // pFirst ----> pItem ----> pRemoveItem ----> pItem ----> 0
203 // pFirst ----> pItem ----------------------> pItem ----> 0
204 //
205 // pFirst ----> pRemoveItem ----> pItem ----> pItem ----> 0
206 // pFirst ----------------------> pItem ----> pItem ----> 0
207 //
208 void USBH_DLIST_Remove(USBH_DLIST_HEAD * pHead, USBH_DLIST_ITEM * pItem)
209 {
210 #if(0)
211 if (pHead->pFirst == pItem)
212 pHead->pFirst->pNext = pItem->pNext; // 0
213 else
214 pItem->pPrev->pNext = pItem->pNext;
215 #else
216 USBH_DLIST_ITEM * pPrevItemOfpItem;
217 if (pHead->pFirst == pItem)
218 pPrevItemOfpItem = pHead->pFirst;
219 else
220 pPrevItemOfpItem = pItem->pPrev;
221
222 pPrevItemOfpItem->pNext = pItem->pNext;
223 #endif
224
225 if (pItem->pNext != 0)
226 {
227 pHead->NumItems = (int) pItem->pPrev;
228 //pHead->NumItems--;
229 }
230 }
231
232 #endif
233
234 //******************************************************************************
235 // Added
236 //******************************************************************************
237 typedef unsigned int (*NODE_MATCH_FUNC)(USBH_DLIST * Entry, void * pContext);
238
239 USBH_DLIST * USBH_X_DLIST_AddNode(USBH_DLIST * pHead,
240 unsigned int NodeEntryOffset, unsigned int NodeSize)
241 {
242 USBH_DLIST * entry = 0;
243 void * node = USBH_Malloc( NodeSize );
244 if (node)
245 {
246 entry = (USBH_DLIST *) ( ( (unsigned int) node ) + NodeEntryOffset );
247 USBH_DLIST_InsertEntry( pHead, entry );
248 }
249 return entry;
250 }
251
252 void USBH_X_DLIST_DeleteNode(USBH_DLIST * Entry, unsigned int EntryOffset)
253 {
254 USBH_DLIST_RemoveEntry( Entry );
255 USBH_Free( (void *) ( (char *) Entry - EntryOffset ) );
256 }
257
258 void USBH_X_DLIST_DeleteAllNodes(USBH_DLIST * pHead, unsigned int EntryOffset)
259 {
260 USBH_DLIST * Entry = pHead->pNext;
261 while ( Entry != pHead )
262 {
263 Entry = Entry->pNext;
264 USBH_X_DLIST_DeleteNode(Entry->pPrev, EntryOffset);
265 }
266 }
267
268 void USBH_X_DLIST_DeleteMatchedNode(USBH_DLIST * pHead,
269 unsigned int EntryOffset, NODE_MATCH_FUNC NodeMacthFunc, void * pContext)
270 {
271 USBH_DLIST * Entry = pHead->pNext;
272 while ( Entry != pHead )
273 {
274 Entry = Entry->pNext;
275 if (NodeMacthFunc( Entry->pPrev, pContext ))
276 {
277 USBH_X_DLIST_DeleteNode(Entry->pPrev, EntryOffset);
278 }
279 }
280 }
281
282 //******************************************************************************
283 // Demo
284 //******************************************************************************
285 // stddef.h
286 // #define offsetof(T, member) (__INTADDR__((&((T *)0)->member)))
287 #define offset_of_member( struct_name, member_name ) \
288 ( (unsigned int) (& ( (struct_name *) 0 ) -> member_name ) )
289
290 #define container_of(ptr, type, member) \
291 ( (type *)( (char *)ptr - offset_of_member(type,member) ) )
292
293 typedef struct HUB_PORT
294 {
295 unsigned int PortNumber;
296 // other members
297 struct USBH_DLIST ListEntry;
298 } HUB_PORT;
299
300 typedef struct USBH_ROOT_HUB
301 {
302 struct USBH_DLIST PortList;
303 unsigned int PortCount;
304 // other members
305 } USBH_ROOT_HUB;
306
307 typedef struct _PortNumberContext
308 {
309 unsigned int PortNumber;
310 } PortNumberContext_t;
311
312 USBH_ROOT_HUB root_hub;
313 HUB_PORT * hub_port[4];
314
315 HUB_PORT * HUB_PORT_Get(USBH_DLIST * Entry)
316 {
317 return container_of( Entry, HUB_PORT, ListEntry );
318 }
319
320 unsigned int MatchPortNumber(USBH_DLIST * Entry, void * pContext)
321 {
322 HUB_PORT * hub_port;
323 PortNumberContext_t * pPortNumberContext;
324 pPortNumberContext = (PortNumberContext_t *)pContext;
325 hub_port = HUB_PORT_Get( Entry );
326 unsigned int ContextPortNumber = pPortNumberContext->PortNumber;
327 unsigned int EntryPortNumber = hub_port->PortNumber;
328 return EntryPortNumber == ContextPortNumber;
329 }
330
331 void USBH_X_DLIST_Test(void)
332 {
333 PortNumberContext_t PortNumberContext;
334
335 USBH_DLIST * ListHead = &root_hub.PortList;
336 USBH_DLIST_Init( ListHead );
337
338 USBH_DLIST * ListEntry;
339 for (unsigned int PortNumber = 0; PortNumber < 4; PortNumber++)
340 {
341 ListEntry = USBH_X_DLIST_AddNode( ListHead, offsetof( HUB_PORT, ListEntry ),
342 sizeof(HUB_PORT) );
343 if ( ListEntry )
344 {
345 hub_port[PortNumber] = HUB_PORT_Get( ListEntry );
346 hub_port[PortNumber]->PortNumber = PortNumber;
347 root_hub.PortCount++;
348 }
349 }
350
351 if ( root_hub.PortCount == 4 )
352 {
353 PortNumberContext.PortNumber = 2;
354 USBH_X_DLIST_DeleteMatchedNode( ListHead, offsetof( HUB_PORT, ListEntry ),
355 MatchPortNumber, &PortNumberContext );
356
357 USBH_X_DLIST_DeleteAllNodes( ListHead, offsetof( HUB_PORT, ListEntry ) );
358 }
359 }