1 /**************************************************************************/
2 /*                                                                        */
3 /*       Copyright (c) Microsoft Corporation. All rights reserved.        */
4 /*                                                                        */
5 /*       This software is licensed under the Microsoft Software License   */
6 /*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
7 /*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
8 /*       and in the root directory of this software.                      */
9 /*                                                                        */
10 /**************************************************************************/
11 
12 
13 /**************************************************************************/
14 /**************************************************************************/
15 /**                                                                       */
16 /** GUIX Component                                                        */
17 /**                                                                       */
18 /**   System Management (System)                                          */
19 /**                                                                       */
20 /**************************************************************************/
21 
22 //#define GX_SOURCE_CODE
23 
24 /* Include necessary system files.  */
25 
26 #include "gx_api.h"
27 #include "gx_system.h"
28 #include "gx_system_rtos_bind.h"
29 
30 
31 /**************************************************************************/
32 /*                                                                        */
33 /*  FUNCTION                                               RELEASE        */
34 /*                                                                        */
35 /*    _gx_system_rtos_bind                                PORTABLE C      */
36 /*                                                           6.1          */
37 /*  AUTHOR                                                                */
38 /*                                                                        */
39 /*    Kenneth Maxwell, Microsoft Corporation                              */
40 /*                                                                        */
41 /*  DESCRIPTION                                                           */
42 /*                                                                        */
43 /*    This file contains a small set of shell functions used to bind GUIX */
44 /*    to a generic RTOS. GUIX is by default configured to run with the    */
45 /*    ThreadX RTOS, but you can port to another RTOS by defining the      */
46 /*    pre-processor directive GX_DISABLE_THREADX_BINDING and completing   */
47 /*    the implementation of the functions found in this file.             */
48 /*    Refer to the GUIX User Guide for more information.                  */
49 /*                                                                        */
50 /*  INPUT                                                                 */
51 /*                                                                        */
52 /*    Refer to GUIX User Guide                                            */
53 /*                                                                        */
54 /*  OUTPUT                                                                */
55 /*                                                                        */
56 /*    Refer to GUIX User Guide                                            */
57 /*                                                                        */
58 /*  CALLS                                                                 */
59 /*                                                                        */
60 /*    Refer to GUIX User Guide                                            */
61 /*                                                                        */
62 /*  CALLED BY                                                             */
63 /*                                                                        */
64 /*    GUIX system serives                                                 */
65 /*                                                                        */
66 /*  RELEASE HISTORY                                                       */
67 /*                                                                        */
68 /*    DATE              NAME                      DESCRIPTION             */
69 /*                                                                        */
70 /*  05-19-2020     Kenneth Maxwell          Initial Version 6.0           */
71 /*  09-30-2020     Kenneth Maxwell          Modified comment(s),          */
72 /*                                            resulting in version 6.1    */
73 /*                                                                        */
74 /**************************************************************************/
75 
76 #ifndef GX_THREADX_BINDING
77 
78 /* This is an example of a generic RTOS binding. We have #ifdefed this code out
79    of the GUIX library build, so that the user attempting to port to a new RTOS
80    will intentionally observe a series of linker errors. These functions need to
81    be implemented in a way that works correctly with the target RTOS.
82 */
83 
84 #if defined(GUIX_BINDING_UCOS_III)
85 
86 #include "os.h"
87 
88 #ifndef OS_CFG_TICK_RATE_HZ
89 #define OS_CFG_TICK_RATE_HZ 100
90 #endif
91 
92 #define GX_TIMER_TASK_PRIORITY   (GX_SYSTEM_THREAD_PRIORITY + 1)
93 #define GX_TIMER_TASK_STACK_SIZE 512
94 void guix_timer_task_entry(void *);
95 
96 /* a few global status variables */
97 GX_BOOL guix_timer_event_pending;
98 
99 /* define stack space for GUIX task */
100 CPU_STK guix_task_stack[GX_THREAD_STACK_SIZE];
101 
102 /* define stack space for timer task */
103 CPU_STK guix_timer_task_stack[GX_TIMER_TASK_STACK_SIZE];
104 
105 /* define semaphore for lock/unlock macros */
106 OS_MUTEX guix_system_lock_mutex;
107 
108 OS_ERR uc_error;
109 OS_TCB guix_tcb;
110 OS_TCB guix_timer_tcb;
111 
112 /* a custom event structure, to hold event and linked list */
113 
114 typedef struct guix_linked_event_struct
115 {
116     GX_EVENT                         event_data;        /* the GUIX event structure */
117     struct guix_linked_event_struct *next;              /* add link member          */
118 } GUIX_LINKED_EVENT;
119 
120 
121 /* a custom fifo event queue structure */
122 
123 typedef struct guix_event_queue_struct
124 {
125     GUIX_LINKED_EVENT *first;           /* first (oldest) event in fifo */
126     GUIX_LINKED_EVENT *last;            /* last (newest) event in fifo  */
127     GUIX_LINKED_EVENT *free;            /* linked list of free events   */
128     GUIX_LINKED_EVENT *free_end;        /* end of the free list         */
129     OS_SEM             count_sem;       /* number of queued events      */
130     OS_MUTEX           lock;            /* lock to protect queue update */
131 } GUIX_EVENT_QUEUE;
132 
133 /* an array of GX_EVENTs used to implement fifo queue */
134 
135 GUIX_LINKED_EVENT guix_event_array[GX_MAX_QUEUE_EVENTS];
136 GUIX_EVENT_QUEUE  guix_event_queue;
137 
138 /* rtos initialize: perform any setup that needs to be done before the GUIX task runs here */
gx_generic_rtos_initialize(VOID)139 VOID   gx_generic_rtos_initialize(VOID)
140 {
141 int Loop;
142 GUIX_LINKED_EVENT *current;
143 
144     guix_timer_event_pending = GX_FALSE;
145     OSMutexCreate(&guix_system_lock_mutex, "gx_system_lock", &uc_error);
146 
147     /* initialize a custom fifo queue structure */
148 
149     guix_event_queue.first = GX_NULL;
150     guix_event_queue.last = GX_NULL;
151     guix_event_queue.free = guix_event_array;
152 
153     current = guix_event_queue.free;
154 
155     /* link all the structures together */
156     for (Loop = 0; Loop < GX_MAX_QUEUE_EVENTS - 1; Loop++)
157     {
158         current -> next = (current + 1);
159         current = current -> next;
160     }
161     current -> next = GX_NULL;                /* terminate the list */
162     guix_event_queue.free_end = current;
163 
164     /* create mutex for lock access to this queue */
165     OSMutexCreate(&guix_event_queue.lock, "gx_queue_lock", &uc_error);
166 
167     /* create counting semaphore to track queue entries */
168     OSSemCreate(&guix_event_queue.count_sem, "gx_queue_count", 0, &uc_error);
169 }
170 
171 VOID (*gx_system_thread_entry)(ULONG);
172 
173 // A small shell function to convert the void * arg expected by uC/OS to
174 // a ULONG parameter expected by GUIX thread entry
gx_system_thread_entry_shell(void * parg)175 void gx_system_thread_entry_shell(void *parg)
176 {
177     gx_system_thread_entry((ULONG) parg);
178 }
179 
180 /* thread_start: start the GUIX thread running. */
gx_generic_thread_start(VOID (* guix_thread_entry)(ULONG))181 UINT   gx_generic_thread_start(VOID(*guix_thread_entry)(ULONG))
182 {
183 
184     /* save the GUIX system thread entry function pointer */
185     gx_system_thread_entry = guix_thread_entry;
186 
187     /* create the main GUIX task */
188 
189     OSTaskCreate(&guix_tcb, "guix_task",
190                  gx_system_thread_entry_shell,
191                  GX_NULL,
192                  GX_SYSTEM_THREAD_PRIORITY,
193                  &guix_task_stack[0],
194                  GX_THREAD_STACK_SIZE - 1,
195                  GX_THREAD_STACK_SIZE,
196                  0, 0, GX_NULL, OS_OPT_TASK_NONE, &uc_error);
197 
198     /* create a simple task to generate timer events into GUIX */
199     OSTaskCreate(&guix_timer_tcb, "guix_timer_task",
200                  guix_timer_task_entry,
201                  GX_NULL,
202                  GX_TIMER_TASK_PRIORITY,
203                  &guix_timer_task_stack[0],
204                  GX_TIMER_TASK_STACK_SIZE -1,
205                  GX_TIMER_TASK_STACK_SIZE,
206                  0, 0, GX_NULL, OS_OPT_TASK_NONE, &uc_error);
207 
208     /* suspend the timer task until needed */
209     OSTaskSuspend(&guix_timer_tcb, &uc_error);
210     return GX_SUCCESS;
211 }
212 
213 /* event_post: push an event into the fifo event queue */
gx_generic_event_post(GX_EVENT * event_ptr)214 UINT   gx_generic_event_post(GX_EVENT *event_ptr)
215 {
216 GUIX_LINKED_EVENT *linked_event;
217 
218     /* lock down the guix event queue */
219     OSMutexPend(&guix_event_queue.lock, 0, OS_OPT_PEND_BLOCKING, NULL, &uc_error);
220 
221     /* grab a free event slot */
222     if (!guix_event_queue.free)
223     {
224         /* there are no free events, return failure */
225         OSMutexPost(&guix_event_queue.lock, OS_OPT_POST_NONE, &uc_error);
226         return GX_FAILURE;
227     }
228 
229     linked_event = guix_event_queue.free;
230     guix_event_queue.free = guix_event_queue.free->next;
231 
232     if (!guix_event_queue.free)
233     {
234         guix_event_queue.free_end = GX_NULL;
235     }
236 
237     /* copy the event data into this slot */
238     linked_event -> event_data = *event_ptr;
239     linked_event -> next = GX_NULL;
240 
241     /* insert this event into fifo queue */
242     if (guix_event_queue.last)
243     {
244         guix_event_queue.last -> next = linked_event;
245     }
246     else
247     {
248         guix_event_queue.first = linked_event;
249     }
250     guix_event_queue.last = linked_event;
251 
252     /* Unlock the guix queue */
253     OSMutexPost(&guix_event_queue.lock, OS_OPT_POST_NONE, &uc_error);
254 
255     /* increment event count */
256     OSSemPost(&guix_event_queue.count_sem, OS_OPT_POST_ALL, &uc_error);
257     return GX_SUCCESS;
258 }
259 
260 /* event_fold: update existing matching event, otherwise post new event */
gx_generic_event_fold(GX_EVENT * event_ptr)261 UINT   gx_generic_event_fold(GX_EVENT *event_ptr)
262 {
263 GUIX_LINKED_EVENT *pTest;
264 
265     /* Lock down the guix queue */
266 
267     OSMutexPend(&guix_event_queue.lock, 0, OS_OPT_PEND_BLOCKING, NULL, &uc_error);
268 
269     // see if the same event is already in the queue:
270     pTest = guix_event_queue.first;
271 
272     while (pTest)
273     {
274         if (pTest -> event_data.gx_event_type == event_ptr -> gx_event_type)
275         {
276             /* found matching event, update it and return */
277             pTest -> event_data.gx_event_payload.gx_event_ulongdata = event_ptr -> gx_event_payload.gx_event_ulongdata;
278             OSMutexPost(&guix_event_queue.lock, OS_OPT_POST_NONE, &uc_error);
279             return GX_SUCCESS;
280         }
281         pTest = pTest -> next;
282     }
283 
284     /* did not find a match, push new event */
285 
286     OSMutexPost(&guix_event_queue.lock, OS_OPT_POST_NONE, &uc_error);
287     gx_generic_event_post(event_ptr);
288     return GX_SUCCESS;
289 }
290 
291 
292 /* event_pop: pop oldest event from fifo queue, block if wait and no events exist */
gx_generic_event_pop(GX_EVENT * put_event,GX_BOOL wait)293 UINT   gx_generic_event_pop(GX_EVENT *put_event, GX_BOOL wait)
294 {
295     if (!wait)
296     {
297         if (guix_event_queue.first == GX_NULL)
298         {
299             /* the queue is empty, just return */
300             return GX_FAILURE;
301         }
302     }
303 
304     /* wait for an event to arrive in queue */
305     OSSemPend(&guix_event_queue.count_sem, 0, OS_OPT_PEND_BLOCKING, NULL, &uc_error);
306 
307     /* lock down the queue */
308     OSMutexPend(&guix_event_queue.lock, 0, OS_OPT_PEND_BLOCKING, NULL, &uc_error);
309 
310     /* copy the event into destination */
311     *put_event = guix_event_queue.first -> event_data;
312 
313     /* link this event holder back into free list */
314     if (guix_event_queue.free_end)
315     {
316         guix_event_queue.free_end -> next = guix_event_queue.first;
317     }
318     else
319     {
320         guix_event_queue.free = guix_event_queue.first;
321     }
322 
323     guix_event_queue.free_end = guix_event_queue.first;
324     guix_event_queue.first = guix_event_queue.first -> next;
325     guix_event_queue.free_end -> next = GX_NULL;
326 
327     if (!guix_event_queue.first)
328     {
329         guix_event_queue.last = GX_NULL;
330     }
331 
332     /* check for popping out a timer event */
333     if (put_event -> gx_event_type == GX_EVENT_TIMER)
334     {
335         guix_timer_event_pending = GX_FALSE;
336     }
337 
338     /* unlock the queue */
339     OSMutexPost(&guix_event_queue.lock, OS_OPT_POST_NONE, &uc_error);
340     return GX_SUCCESS;
341 }
342 
343 /* event_purge: delete events targetted to particular widget */
gx_generic_event_purge(GX_WIDGET * target)344 VOID   gx_generic_event_purge(GX_WIDGET *target)
345 {
346 GX_BOOL Purge;
347 GUIX_LINKED_EVENT *pTest;
348 
349     /* Lock down the guix queue */
350 
351     OSMutexPend(&guix_event_queue.lock, 0, OS_OPT_PEND_BLOCKING, NULL, &uc_error);
352 
353     // look for events targetted to widget or widget children:
354     pTest = guix_event_queue.first;
355 
356     while (pTest)
357     {
358         Purge = GX_FALSE;
359 
360         if (pTest ->event_data.gx_event_target)
361         {
362             if (pTest -> event_data.gx_event_target == target)
363             {
364                 Purge = GX_TRUE;
365             }
366             else
367             {
368                 gx_widget_child_detect(target, pTest->event_data.gx_event_target, &Purge);
369             }
370             if (Purge)
371             {
372                 pTest ->event_data.gx_event_target = GX_NULL;
373                 pTest->event_data.gx_event_type = 0;
374             }
375         }
376         pTest = pTest -> next;
377     }
378 
379     OSMutexPost(&guix_event_queue.lock, OS_OPT_POST_NONE, &uc_error);
380 }
381 
382 /* start the RTOS timer */
gx_generic_timer_start(VOID)383 VOID   gx_generic_timer_start(VOID)
384 {
385     OSTaskResume(&guix_timer_tcb, &uc_error);
386 }
387 
388 /* stop the RTOS timer */
gx_generic_timer_stop(VOID)389 VOID   gx_generic_timer_stop(VOID)
390 {
391     OSTaskSuspend(&guix_timer_tcb, &uc_error);
392 }
393 
394 /* lock the system protection mutex */
gx_generic_system_mutex_lock(VOID)395 VOID   gx_generic_system_mutex_lock(VOID)
396 {
397     OSMutexPend(&guix_system_lock_mutex, 0, OS_OPT_PEND_BLOCKING, NULL, &uc_error);
398 
399 }
400 
401 /* unlock system protection mutex */
gx_generic_system_mutex_unlock(VOID)402 VOID   gx_generic_system_mutex_unlock(VOID)
403 {
404     OSMutexPost(&guix_system_lock_mutex, OS_OPT_POST_NONE, &uc_error);
405 }
406 
407 /* return number of low-level system timer ticks. Used for pen speed caculations */
gx_generic_system_time_get(VOID)408 ULONG  gx_generic_system_time_get(VOID)
409 {
410     return((ULONG)OSTimeGet(&uc_error));
411 }
412 
413 /* thread_identify: return current thread identifier, cast as VOID * */
gx_generic_thread_identify(VOID)414 VOID  *gx_generic_thread_identify(VOID)
415 {
416     return((VOID *)OSTCBCurPtr);
417 }
418 
419 /* a simple task to drive the GUIX timer mechanism */
guix_timer_task_entry(void * unused)420 void guix_timer_task_entry(void *unused)
421 {
422 int TickCount = OS_CFG_TICK_RATE_HZ / GX_TICKS_SECOND;
423 
424     if (TickCount <= 0)
425     {
426         TickCount = 1;
427     }
428 
429     while (1)
430     {
431         OSTimeDly(TickCount, OS_OPT_TIME_DLY, &uc_error);
432 
433         /* prevent sending timer events faster than they can be processed */
434         if (!guix_timer_event_pending)
435         {
436             guix_timer_event_pending = GX_TRUE;
437             _gx_system_timer_expiration(0);
438         }
439     }
440 }
441 
gx_generic_time_delay(int ticks)442 VOID gx_generic_time_delay(int ticks)
443 {
444     OSTimeDly(ticks, OS_OPT_TIME_DLY, &uc_error);
445 }
446 
447 
448 #endif  /* Binding for UCOS-III enabled */
449 
450 #if defined(GUIX_BINDING_UCOS_II)
451 
452 #include "ucos_ii.h"
453 
454 #define TIMER_TASK_PRIORITY   (GX_SYSTEM_THREAD_PRIORITY + 1)
455 #define TIMER_TASK_STACK_SIZE 512
456 void guix_timer_task_entry(void *);
457 
458 /* a few global status variables */
459 GX_BOOL guix_timer_event_pending;
460 INT8U   guix_uc_err = 0;
461 
462 /* define stack space for GUIX task */
463 OS_STK guix_task_stack[GX_THREAD_STACK_SIZE];
464 OS_STK guix_task_stack[GX_THREAD_STACK_SIZE];
465 
466 /* define stack space for timer task */
467 OS_STK guix_timer_task_stack[TIMER_TASK_STACK_SIZE];
468 
469 /* define semaphore for lock/unlock macros */
470 OS_EVENT *guix_system_lock_semaphore;
471 
472 /* a custom event structure, to hold event and linked list */
473 
474 typedef struct guix_linked_event_struct
475 {
476     GX_EVENT                         event_data;        /* the GUIX event structure */
477     struct guix_linked_event_struct *next;              /* add link member          */
478 } GUIX_LINKED_EVENT;
479 
480 
481 /* a custom fifo event queue structure */
482 
483 typedef struct guix_event_queue_struct
484 {
485     GUIX_LINKED_EVENT *first;           /* first (oldest) event in fifo */
486     GUIX_LINKED_EVENT *last;            /* last (newest) event in fifo  */
487     GUIX_LINKED_EVENT *free;            /* linked list of free events   */
488     GUIX_LINKED_EVENT *free_end;        /* end of the free list         */
489     OS_EVENT          *count_sem;       /* number of queued events      */
490     OS_EVENT          *lock_sem;        /* lock to protect queue update */
491 } GUIX_EVENT_QUEUE;
492 
493 /* an array of GX_EVENTs used to implement fifo queue */
494 
495 GUIX_LINKED_EVENT guix_event_array[GX_MAX_QUEUE_EVENTS];
496 GUIX_EVENT_QUEUE  guix_event_queue;
497 
498 /* rtos initialize: perform any setup that needs to be done before the GUIX task runs here */
gx_generic_rtos_initialize(VOID)499 VOID   gx_generic_rtos_initialize(VOID)
500 {
501 int Loop;
502 GUIX_LINKED_EVENT *current;
503 
504     guix_timer_event_pending = GX_FALSE;
505     guix_system_lock_semaphore = OSSemCreate(1);
506 
507     /* initialize a custom fifo queue structure */
508 
509     guix_event_queue.first = GX_NULL;
510     guix_event_queue.last = GX_NULL;
511     guix_event_queue.free = guix_event_array;
512 
513     current = guix_event_queue.free;
514 
515     /* link all the structures together */
516     for (Loop = 0; Loop < GX_MAX_QUEUE_EVENTS - 1; Loop++)
517     {
518         current -> next = (current + 1);
519         current = current -> next;
520     }
521     current -> next = GX_NULL;                /* terminate the list */
522     guix_event_queue.free_end = current;
523 
524     /* create mutex for lock access to this queue */
525     guix_event_queue.lock_sem = OSSemCreate(1);
526 
527     /* create counting semaphore to track queue entries */
528     guix_event_queue.count_sem = OSSemCreate(0);
529 }
530 
531 /* A variable to store GUIX thread entry function pointer */
532 VOID (*gx_thread_entry)(ULONG);
533 
534 /* a simple shell function to convert the UCOS (void *)
535    parameter to the GUIX ULONG param type. */
guix_thread_entry_shell(void * ptr)536 void guix_thread_entry_shell(void *ptr)
537 {
538     gx_thread_entry((ULONG) ptr);
539 }
540 
541 /* thread_start: start the GUIX thread running. */
gx_generic_thread_start(VOID (* guix_thread_entry)(ULONG))542 UINT   gx_generic_thread_start(VOID(*guix_thread_entry)(ULONG))
543 {
544     /* save pointer to GUIX thread entry function */
545     gx_thread_entry = guix_thread_entry;
546 
547     /* create the main GUIX task */
548     OSTaskCreate(guix_thread_entry_shell, (void *)0,
549                  &guix_task_stack[GX_THREAD_STACK_SIZE - 1], GX_SYSTEM_THREAD_PRIORITY);
550 
551     /* create a simple task to generate timer events into GUIX */
552     OSTaskCreate(guix_timer_task_entry, (void *)0,
553                  &guix_timer_task_stack[TIMER_TASK_STACK_SIZE - 1], TIMER_TASK_PRIORITY);
554 
555     /* suspend the timer task until needed */
556     OSTaskSuspend(TIMER_TASK_PRIORITY);
557     return GX_SUCCESS;
558 }
559 
560 /* event_post: push an event into the fifo event queue */
gx_generic_event_post(GX_EVENT * event_ptr)561 UINT   gx_generic_event_post(GX_EVENT *event_ptr)
562 {
563 GUIX_LINKED_EVENT *linked_event;
564 
565     /* lock down the guix event queue */
566     OSSemPend(guix_event_queue.lock_sem, 0, &guix_uc_err);
567 
568     /* grab a free event slot */
569     if (!guix_event_queue.free)
570     {
571         /* there are no free events, return failure */
572         OSSemPost(guix_event_queue.lock_sem);
573         return GX_FAILURE;
574     }
575 
576     linked_event = guix_event_queue.free;
577     guix_event_queue.free = guix_event_queue.free->next;
578 
579     if (!guix_event_queue.free)
580     {
581         guix_event_queue.free_end = GX_NULL;
582     }
583 
584     /* copy the event data into this slot */
585     linked_event -> event_data = *event_ptr;
586     linked_event -> next = GX_NULL;
587 
588     /* insert this event into fifo queue */
589     if (guix_event_queue.last)
590     {
591         guix_event_queue.last -> next = linked_event;
592     }
593     else
594     {
595         guix_event_queue.first = linked_event;
596     }
597     guix_event_queue.last = linked_event;
598 
599     /* Unlock the guix queue */
600     OSSemPost(guix_event_queue.lock_sem);
601 
602     /* increment event count */
603     OSSemPost(guix_event_queue.count_sem);
604     return GX_SUCCESS;
605 }
606 
607 /* event_fold: update existing matching event, otherwise post new event */
gx_generic_event_fold(GX_EVENT * event_ptr)608 UINT   gx_generic_event_fold(GX_EVENT *event_ptr)
609 {
610 GUIX_LINKED_EVENT *pTest;
611 
612     /* Lock down the guix queue */
613 
614     OSSemPend(guix_event_queue.lock_sem, 0, &guix_uc_err);
615 
616     // see if the same event is already in the queue:
617     pTest = guix_event_queue.first;
618 
619     while (pTest)
620     {
621         if (pTest -> event_data.gx_event_type == event_ptr -> gx_event_type)
622         {
623             /* found matching event, update it and return */
624             pTest -> event_data.gx_event_payload.gx_event_ulongdata = event_ptr -> gx_event_payload.gx_event_ulongdata;
625             OSSemPost(guix_event_queue.lock_sem);
626             return GX_SUCCESS;
627         }
628         pTest = pTest -> next;
629     }
630 
631     /* did not find a match, push new event */
632 
633     OSSemPost(guix_event_queue.lock_sem);
634     gx_generic_event_post(event_ptr);
635     return GX_SUCCESS;
636 }
637 
638 
639 /* event_pop: pop oldest event from fifo queue, block if wait and no events exist */
gx_generic_event_pop(GX_EVENT * put_event,GX_BOOL wait)640 UINT   gx_generic_event_pop(GX_EVENT *put_event, GX_BOOL wait)
641 {
642     if (!wait)
643     {
644         if (guix_event_queue.first == GX_NULL)
645         {
646             /* the queue is empty, just return */
647             OSSemPost(guix_event_queue.lock_sem);
648             return GX_FAILURE;
649         }
650     }
651 
652     /* wait for an event to arrive in queue */
653     OSSemPend(guix_event_queue.count_sem, 0, &guix_uc_err);
654 
655     /* lock down the queue */
656     OSSemPend(guix_event_queue.lock_sem, 0, &guix_uc_err);
657 
658     /* copy the event into destination */
659     *put_event = guix_event_queue.first -> event_data;
660 
661     /* link this event holder back into free list */
662     if (guix_event_queue.free_end)
663     {
664         guix_event_queue.free_end -> next = guix_event_queue.first;
665     }
666     else
667     {
668         guix_event_queue.free = guix_event_queue.first;
669     }
670 
671     guix_event_queue.free_end = guix_event_queue.first;
672     guix_event_queue.first = guix_event_queue.first -> next;
673     guix_event_queue.free_end -> next = GX_NULL;
674 
675     if (!guix_event_queue.first)
676     {
677         guix_event_queue.last = GX_NULL;
678     }
679 
680     /* check for popping out a timer event */
681     if (put_event -> gx_event_type == GX_EVENT_TIMER)
682     {
683         guix_timer_event_pending = GX_FALSE;
684     }
685 
686     /* unlock the queue */
687     OSSemPost(guix_event_queue.lock_sem);
688     return GX_SUCCESS;
689 }
690 
691 /* event_purge: delete events targetted to particular widget */
gx_generic_event_purge(GX_WIDGET * target)692 VOID   gx_generic_event_purge(GX_WIDGET *target)
693 {
694 GX_BOOL Purge;
695 GUIX_LINKED_EVENT *pTest;
696 
697     /* Lock down the guix queue */
698 
699     OSSemPend(guix_event_queue.lock_sem, 0, &guix_uc_err);
700 
701     // look for events targetted to widget or widget children:
702     pTest = guix_event_queue.first;
703 
704     while (pTest)
705     {
706         Purge = GX_FALSE;
707 
708         if (pTest ->event_data.gx_event_target)
709         {
710             if (pTest -> event_data.gx_event_target == target)
711             {
712                 Purge = GX_TRUE;
713             }
714             else
715             {
716                 gx_widget_child_detect(target, pTest->event_data.gx_event_target, &Purge);
717             }
718             if (Purge)
719             {
720                 pTest ->event_data.gx_event_target = GX_NULL;
721                 pTest->event_data.gx_event_type = 0;
722             }
723         }
724         pTest = pTest -> next;
725     }
726 
727     OSSemPost(guix_event_queue.lock_sem);
728 }
729 
730 /* start the RTOS timer */
gx_generic_timer_start(VOID)731 VOID   gx_generic_timer_start(VOID)
732 {
733     OSTaskResume(TIMER_TASK_PRIORITY);
734 }
735 
736 /* stop the RTOS timer */
gx_generic_timer_stop(VOID)737 VOID   gx_generic_timer_stop(VOID)
738 {
739     OSTaskSuspend(TIMER_TASK_PRIORITY);
740 }
741 
742 /* lock the system protection mutex */
gx_generic_system_mutex_lock(VOID)743 VOID   gx_generic_system_mutex_lock(VOID)
744 {
745     OSSemPend(guix_system_lock_semaphore, 0, &guix_uc_err);
746 }
747 
748 /* unlock system protection mutex */
gx_generic_system_mutex_unlock(VOID)749 VOID   gx_generic_system_mutex_unlock(VOID)
750 {
751     OSSemPost(guix_system_lock_semaphore);
752 }
753 
754 /* return number of low-level system timer ticks. Used for pen speed caculations */
gx_generic_system_time_get(VOID)755 ULONG  gx_generic_system_time_get(VOID)
756 {
757     return((ULONG)OSTimeGet());
758 }
759 
760 /* thread_identify: return current thread identifier, cast as VOID * */
gx_generic_thread_identify(VOID)761 VOID  *gx_generic_thread_identify(VOID)
762 {
763     return((VOID *)OSTCBCur);
764 }
765 
766 /* a simple task to drive the GUIX timer mechanism */
guix_timer_task_entry(VOID * unused)767 VOID guix_timer_task_entry(VOID *unused)
768 {
769 int TickCount = OS_TICKS_PER_SEC / GX_TICKS_SECOND;
770 
771     if (TickCount <= 0)
772     {
773         TickCount = 1;
774     }
775 
776     while (1)
777     {
778         OSTimeDly(TickCount);
779 
780         /* prevent sending timer events faster than they can be processed */
781         if (!guix_timer_event_pending)
782         {
783             guix_timer_event_pending = GX_TRUE;
784             _gx_system_timer_expiration(0);
785         }
786     }
787 }
788 
gx_generic_time_delay(int ticks)789 VOID gx_generic_time_delay(int ticks)
790 {
791     OSTimeDly(ticks);
792 }
793 
794 
795 #endif /* Binding for UCOS-II enabled */
796 
797 #endif  /* if !ThreadX */
798 
799 
800