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 /** USBX Component                                                        */
17 /**                                                                       */
18 /**   Pictbridge Application                                              */
19 /**                                                                       */
20 /**************************************************************************/
21 /**************************************************************************/
22 
23 
24 /* Include necessary system files.  */
25 
26 #define UX_SOURCE_CODE
27 
28 #include "ux_api.h"
29 #include "ux_pictbridge.h"
30 #include "ux_device_stack.h"
31 #include "ux_device_class_pima.h"
32 
33 
34 /**************************************************************************/
35 /*                                                                        */
36 /*  FUNCTION                                               RELEASE        */
37 /*                                                                        */
38 /*    _ux_pictbridge_dpsclient_start                      PORTABLE C      */
39 /*                                                           6.1.12       */
40 /*  AUTHOR                                                                */
41 /*                                                                        */
42 /*    Chaoqiong Xiao, Microsoft Corporation                               */
43 /*                                                                        */
44 /*  DESCRIPTION                                                           */
45 /*                                                                        */
46 /*    This function starts the DPS client (usually a camera or phone)     */
47 /*                                                                        */
48 /*  INPUT                                                                 */
49 /*                                                                        */
50 /*    pima                                   Pima instance associated     */
51 /*                                                                        */
52 /*  OUTPUT                                                                */
53 /*                                                                        */
54 /*    Completion Status                                                   */
55 /*                                                                        */
56 /*  CALLS                                                                 */
57 /*                                                                        */
58 /*                                                                        */
59 /*  CALLED BY                                                             */
60 /*                                                                        */
61 /*    user application                                                    */
62 /*                                                                        */
63 /*  RELEASE HISTORY                                                       */
64 /*                                                                        */
65 /*    DATE              NAME                      DESCRIPTION             */
66 /*                                                                        */
67 /*  05-19-2020     Chaoqiong Xiao           Initial Version 6.0           */
68 /*  09-30-2020     Chaoqiong Xiao           Modified comment(s),          */
69 /*                                            used UX prefix to refer to  */
70 /*                                            TX symbols instead of using */
71 /*                                            them directly,              */
72 /*                                            resulting in version 6.1    */
73 /*  07-29-2022     Chaoqiong Xiao           Modified comment(s),          */
74 /*                                            used macros for RTOS calls, */
75 /*                                            resulting in version 6.1.12 */
76 /*                                                                        */
77 /**************************************************************************/
_ux_pictbridge_dpsclient_start(UX_PICTBRIDGE * pictbridge)78 UINT  _ux_pictbridge_dpsclient_start(UX_PICTBRIDGE *pictbridge)
79 {
80 UINT                                status;
81 UX_SLAVE_CLASS_PIMA_OBJECT          *object_info;
82 
83     /* Allocate 1 object for the host.  */
84     pictbridge -> ux_pictbridge_object_host = _ux_utility_memory_allocate(UX_NO_ALIGN, UX_CACHE_SAFE_MEMORY, sizeof(UX_SLAVE_CLASS_PIMA_OBJECT));
85 
86     /* Check status. */
87     if (pictbridge -> ux_pictbridge_object_host  == UX_NULL)
88         return(UX_MEMORY_INSUFFICIENT);
89 
90     /* Initialize status to success for things going on.  */
91     status = UX_SUCCESS;
92 
93     /* Allocate 1 object for the client.  */
94     pictbridge -> ux_pictbridge_object_client = (VOID *)_ux_utility_memory_allocate(UX_NO_ALIGN, UX_CACHE_SAFE_MEMORY, sizeof(UX_SLAVE_CLASS_PIMA_OBJECT));
95 
96     /* Check status. */
97     if (pictbridge -> ux_pictbridge_object_client  == UX_NULL)
98         status = (UX_MEMORY_INSUFFICIENT);
99 
100     /* Allocate 1 object for the job.  */
101     if (status == UX_SUCCESS)
102     {
103         pictbridge -> ux_pictbridge_jobinfo.ux_pictbridge_jobinfo_object = (VOID *)_ux_utility_memory_allocate(UX_NO_ALIGN, UX_CACHE_SAFE_MEMORY, sizeof(UX_SLAVE_CLASS_PIMA_OBJECT));
104 
105         /* Check status. */
106         if (pictbridge -> ux_pictbridge_jobinfo.ux_pictbridge_jobinfo_object  == UX_NULL)
107             status = (UX_MEMORY_INSUFFICIENT);
108     }
109 
110     /* Allocate some memory for the XML objects.  For the client script. */
111     if (status == UX_SUCCESS)
112     {
113         object_info = (UX_SLAVE_CLASS_PIMA_OBJECT *) pictbridge -> ux_pictbridge_object_client;
114         object_info -> ux_device_class_pima_object_buffer = _ux_utility_memory_allocate(UX_NO_ALIGN, UX_CACHE_SAFE_MEMORY, UX_PICTBRIDGE_MAX_PIMA_OBJECT_BUFFER);
115 
116         /* Check status. */
117         if (object_info -> ux_device_class_pima_object_buffer == UX_NULL)
118             status = (UX_MEMORY_INSUFFICIENT);
119     }
120 
121     /* Allocate some memory for the XML objects.  For the host script. */
122     if (status == UX_SUCCESS)
123     {
124         object_info = (UX_SLAVE_CLASS_PIMA_OBJECT *)  pictbridge -> ux_pictbridge_object_host;
125         object_info -> ux_device_class_pima_object_buffer = _ux_utility_memory_allocate(UX_NO_ALIGN, UX_CACHE_SAFE_MEMORY, UX_PICTBRIDGE_MAX_PIMA_OBJECT_BUFFER);
126 
127         /* Check status. */
128         if (object_info -> ux_device_class_pima_object_buffer == UX_NULL)
129             return(UX_MEMORY_INSUFFICIENT);
130     }
131 
132     /* Create a event flag group for the client to communicate with the application.  */
133     if (status == UX_SUCCESS)
134     {
135         status =  _ux_system_event_flags_create(&pictbridge -> ux_pictbridge_event_flags_group, "ux_pictbridge_client_event_flag");
136 
137         /* Check status.  */
138         if (status != UX_SUCCESS)
139 
140             /* Do not proceed if error.  */
141             status = (UX_EVENT_ERROR);
142     }
143 
144     /* Create the semaphore to wake up the thread.  */
145     if (status == UX_SUCCESS)
146     {
147         status =  _ux_system_semaphore_create(&pictbridge -> ux_pictbridge_notification_semaphore, "ux_pictbridge_client_semaphore", 0);
148         if (status != UX_SUCCESS)
149 
150             /* Do not proceed if error.  */
151             status = (UX_SEMAPHORE_ERROR);
152     }
153 
154     /* Allocate a Thread stack.  */
155     if (status == UX_SUCCESS)
156     {
157         pictbridge -> ux_pictbridge_thread_stack =
158                     _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, UX_PICTBRIDGE_THREAD_STACK_SIZE);
159 
160         /* Check the completion status.  */
161         if (pictbridge -> ux_pictbridge_thread_stack == UX_NULL)
162 
163             /* Do not proceed if error.  */
164             return(UX_MEMORY_INSUFFICIENT);
165     }
166 
167     /* Create the pictbridge class thread.  */
168     if (status == UX_SUCCESS)
169     {
170         status =  _ux_system_thread_create(&pictbridge -> ux_pictbridge_thread,
171                                 "ux_pictbridge_thread", _ux_pictbridge_dpsclient_thread,
172                                 (ULONG)(ALIGN_TYPE) pictbridge,
173                                 pictbridge -> ux_pictbridge_thread_stack,
174                                 UX_PICTBRIDGE_THREAD_STACK_SIZE,
175                                 UX_PICTBRIDGE_THREAD_PRIORITY_CLASS,
176                                 UX_PICTBRIDGE_THREAD_PRIORITY_CLASS,
177                                 UX_NO_TIME_SLICE, UX_AUTO_START);
178 
179         /* Check the completion status.  */
180         if (status != UX_SUCCESS)
181 
182             /* Do not proceed if error.  */
183             status = (UX_THREAD_ERROR);
184 
185         UX_THREAD_EXTENSION_PTR_SET(&(pictbridge -> ux_pictbridge_thread), pictbridge)
186     }
187 
188     /* Go on to next step.  */
189     if (status == UX_SUCCESS)
190     {
191         /* Initialize the pictbridge request/response state to request expected.  */
192         pictbridge -> ux_pictbridge_request_response = UX_PICTBRIDGE_REQUEST;
193 
194         /* Set the host/client cycle to idle.  */
195         pictbridge -> ux_pictbridge_host_client_state_machine = UX_PICTBRIDGE_STATE_MACHINE_IDLE;
196 
197         /* Initialize the first XML object valid in the pictbridge instance.  Initialize the handle, type and file name.
198         The storage handle and the object handle have a fixed value of 1 in our implementation. */
199         object_info = pictbridge -> ux_pictbridge_object_client;
200         object_info -> ux_device_class_pima_object_format = UX_DEVICE_CLASS_PIMA_OFC_SCRIPT;
201         object_info -> ux_device_class_pima_object_storage_id = 1;
202         object_info -> ux_device_class_pima_object_handle_id = 2;
203         _ux_utility_string_to_unicode(_ux_pictbridge_ddiscovery_name, object_info -> ux_device_class_pima_object_filename);
204 
205         /* Initialize the head and tail of the notification round robin buffers.
206         At first, the head and tail are pointing to the beginning of the array.  */
207         pictbridge -> ux_pictbridge_event_array_head =  pictbridge -> ux_pictbridge_event_array;
208         pictbridge -> ux_pictbridge_event_array_tail =  pictbridge -> ux_pictbridge_event_array;
209         pictbridge -> ux_pictbridge_event_array_end  =  pictbridge -> ux_pictbridge_event_array + UX_PICTBRIDGE_MAX_EVENT_NUMBER;
210 
211         /* Initialize the pima device parameter.  */
212         pictbridge -> ux_pictbridge_pima_parameter.ux_device_class_pima_parameter_manufacturer                  = pictbridge -> ux_pictbridge_dpslocal.ux_pictbridge_devinfo_vendor_name;
213         pictbridge -> ux_pictbridge_pima_parameter.ux_device_class_pima_parameter_model                         = pictbridge -> ux_pictbridge_dpslocal.ux_pictbridge_devinfo_product_name;
214         pictbridge -> ux_pictbridge_pima_parameter.ux_device_class_pima_parameter_serial_number                 = pictbridge -> ux_pictbridge_dpslocal.ux_pictbridge_devinfo_serial_no;
215         pictbridge -> ux_pictbridge_pima_parameter.ux_device_class_pima_parameter_storage_id                    = 1;
216         pictbridge -> ux_pictbridge_pima_parameter.ux_device_class_pima_parameter_storage_type                  = UX_DEVICE_CLASS_PIMA_STC_FIXED_RAM;
217         pictbridge -> ux_pictbridge_pima_parameter.ux_device_class_pima_parameter_storage_file_system_type      = UX_DEVICE_CLASS_PIMA_FSTC_GENERIC_FLAT;
218         pictbridge -> ux_pictbridge_pima_parameter.ux_device_class_pima_parameter_storage_access_capability     = UX_DEVICE_CLASS_PIMA_AC_READ_WRITE;
219         pictbridge -> ux_pictbridge_pima_parameter.ux_device_class_pima_parameter_storage_max_capacity_low      = pictbridge -> ux_pictbridge_dpslocal.ux_pictbridge_devinfo_storage_size;
220         pictbridge -> ux_pictbridge_pima_parameter.ux_device_class_pima_parameter_storage_max_capacity_high     = 0;
221         pictbridge -> ux_pictbridge_pima_parameter.ux_device_class_pima_parameter_storage_free_space_low        = pictbridge -> ux_pictbridge_dpslocal.ux_pictbridge_devinfo_storage_size;
222         pictbridge -> ux_pictbridge_pima_parameter.ux_device_class_pima_parameter_storage_free_space_high       = 0;
223         pictbridge -> ux_pictbridge_pima_parameter.ux_device_class_pima_parameter_storage_free_space_image      = 0;
224         pictbridge -> ux_pictbridge_pima_parameter.ux_device_class_pima_parameter_storage_description           = _ux_pictbridge_volume_description;
225         pictbridge -> ux_pictbridge_pima_parameter.ux_device_class_pima_parameter_storage_volume_label          = _ux_pictbridge_volume_label;
226         pictbridge -> ux_pictbridge_pima_parameter.ux_device_class_pima_parameter_object_number_get             = _ux_pictbridge_dpsclient_object_number_get;
227         pictbridge -> ux_pictbridge_pima_parameter.ux_device_class_pima_parameter_object_handles_get            = _ux_pictbridge_dpsclient_object_handles_get;
228         pictbridge -> ux_pictbridge_pima_parameter.ux_device_class_pima_parameter_object_info_get               = _ux_pictbridge_dpsclient_object_info_get;
229         pictbridge -> ux_pictbridge_pima_parameter.ux_device_class_pima_parameter_object_data_get               = _ux_pictbridge_dpsclient_object_data_get;
230         pictbridge -> ux_pictbridge_pima_parameter.ux_device_class_pima_parameter_object_info_send              = _ux_pictbridge_dpsclient_object_info_send;
231         pictbridge -> ux_pictbridge_pima_parameter.ux_device_class_pima_parameter_object_data_send              = _ux_pictbridge_dpsclient_object_data_send;
232         pictbridge -> ux_pictbridge_pima_parameter.ux_device_class_pima_parameter_object_delete                 = _ux_pictbridge_dpsclient_object_delete;
233 
234         /* Store the instance owner.  */
235         pictbridge -> ux_pictbridge_pima_parameter.ux_device_class_pima_parameter_application                   = (VOID *) pictbridge;
236 
237         /* Initialize the device pima class. The class is connected with interface 0 */
238         status = _ux_device_stack_class_register(_ux_system_slave_class_pima_name, _ux_device_class_pima_entry,
239                                                     1, 0, (VOID *)&pictbridge -> ux_pictbridge_pima_parameter);
240     }
241 
242     /* Check status.  */
243     if (status != UX_SUCCESS)
244     {
245 
246         /* Free resources allocated so far.  */
247         if (_ux_system_thread_created(&pictbridge -> ux_pictbridge_thread))
248             _ux_system_thread_delete(&pictbridge -> ux_pictbridge_thread);
249         if (pictbridge -> ux_pictbridge_thread_stack)
250             _ux_utility_memory_free(pictbridge -> ux_pictbridge_thread_stack);
251         if (_ux_system_semaphore_created(&pictbridge -> ux_pictbridge_notification_semaphore))
252             _ux_system_semaphore_delete(&pictbridge -> ux_pictbridge_notification_semaphore);
253         if (_ux_system_event_flags_created(&pictbridge -> ux_pictbridge_event_flags_group))
254             _ux_system_event_flags_delete(&pictbridge -> ux_pictbridge_event_flags_group);
255         if (pictbridge -> ux_pictbridge_jobinfo.ux_pictbridge_jobinfo_object)
256         {
257             _ux_utility_memory_free(pictbridge -> ux_pictbridge_jobinfo.ux_pictbridge_jobinfo_object);
258         }
259         if (pictbridge -> ux_pictbridge_object_client)
260         {
261             object_info = (UX_SLAVE_CLASS_PIMA_OBJECT *) pictbridge -> ux_pictbridge_object_client;
262             if (object_info -> ux_device_class_pima_object_buffer)
263                 _ux_utility_memory_free(object_info -> ux_device_class_pima_object_buffer);
264             _ux_utility_memory_free(pictbridge -> ux_pictbridge_object_client);
265         }
266         object_info = (UX_SLAVE_CLASS_PIMA_OBJECT *)  pictbridge -> ux_pictbridge_object_host;
267         if (object_info -> ux_device_class_pima_object_buffer)
268             _ux_utility_memory_free(object_info -> ux_device_class_pima_object_buffer);
269         _ux_utility_memory_free(pictbridge -> ux_pictbridge_object_host);
270 
271         /* Do not proceed if error.  */
272         return(status);
273     }
274 
275     /* We are done.  */
276     return(UX_SUCCESS);
277 }
278 
279