Double Link List
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 }