1 /* This test is designed to test the simple dpump host/device class operation.  */
2 
3 #include <stdio.h>
4 #include "tx_api.h"
5 #include "ux_api.h"
6 #include "ux_system.h"
7 #include "ux_utility.h"
8 #include "ux_hcd_sim_host.h"
9 
10 #include "fx_api.h"
11 
12 #include "ux_device_class_dfu.h"
13 #include "ux_device_stack.h"
14 #include "ux_host_stack.h"
15 
16 #include "ux_test_dcd_sim_slave.h"
17 #include "ux_test_hcd_sim_host.h"
18 #include "ux_test_utility_sim.h"
19 
20 
21 #define UX_DEMO_REQUEST_MAX_LENGTH                                                 \
22     ((UX_HCD_SIM_HOST_MAX_PAYLOAD) > (UX_SLAVE_REQUEST_DATA_MAX_LENGTH) ?         \
23      (UX_HCD_SIM_HOST_MAX_PAYLOAD) : (UX_SLAVE_REQUEST_DATA_MAX_LENGTH))
24 
25 
26 /* Define constants.  */
27 
28 #define  UX_DEMO_MEMORY_SIZE             (128*1024)
29 #define  UX_DEMO_STACK_SIZE              (1024)
30 
31 /* Define local/extern function prototypes.  */
32 
33 static void        test_thread_entry(ULONG);
34 static TX_THREAD   tx_test_thread_host_simulation;
35 static TX_THREAD   tx_test_thread_slave_simulation;
36 
37 static VOID        demo_thread_dfu_activate(VOID *dfu);
38 static VOID        demo_thread_dfu_deactivate(VOID *dfu);
39 static UINT        demo_thread_dfu_read(VOID *dfu, ULONG block_number, UCHAR * data_pointer, ULONG length, ULONG *actual_length);
40 static UINT        demo_thread_dfu_write(VOID *dfu, ULONG block_number, UCHAR * data_pointer, ULONG length, ULONG *media_status);
41 static UINT        demo_thread_dfu_get_status(VOID *dfu, ULONG *media_status);
42 static UINT        demo_thread_dfu_notify(VOID *dfu, ULONG notification);
43 static UINT        demo_thread_dfu_custom_request(VOID *dfu, UX_SLAVE_TRANSFER *transfer);
44 static void        ux_test_thread_simulation_0_entry(ULONG);
45 /* Define global data structures.  */
46 
47 static UCHAR                               usbx_memory[UX_DEMO_MEMORY_SIZE + (UX_DEMO_STACK_SIZE * 2)];
48 
49 static ULONG                               error_counter;
50 
51 static ULONG                               set_cfg_counter;
52 
53 static ULONG                               rsc_mem_free_on_set_cfg;
54 static ULONG                               rsc_sem_on_set_cfg;
55 static ULONG                               rsc_sem_get_on_set_cfg;
56 static ULONG                               rsc_mutex_on_set_cfg;
57 
58 static ULONG                               rsc_enum_sem_usage;
59 static ULONG                               rsc_enum_sem_get_count;
60 static ULONG                               rsc_enum_mutex_usage;
61 static ULONG                               rsc_enum_mem_usage;
62 
63 static ULONG                               interaction_count;
64 
65 static UCHAR                               error_callback_ignore = UX_TRUE;
66 static ULONG                               error_callback_counter;
67 
68 static UX_SLAVE_CLASS_DFU_PARAMETER        dfu_parameter;
69 
70 static UX_DEVICE                           *device;
71 static ULONG                               dfu_block;
72 static ULONG                               dfu_transfer_length;
73 static ULONG                               dfu_actual_length;
74 static UCHAR                               dfu_host_buffer[UX_DEMO_REQUEST_MAX_LENGTH];
75 static UCHAR                               dfu_device_buffer[UX_DEMO_REQUEST_MAX_LENGTH];
76 
77 static TX_THREAD                           ux_test_thread_simulation_0;
78 /* Define device framework.  */
79 
80 /* DFU descriptor must be same for all frameworks!!!  */
81 #define DFU_FUNCTION_DESCRIPTOR                                                 \
82     /* Functional descriptor for DFU.  */                                       \
83     0x09, 0x21,                                                                 \
84     0x0f,       /* bmAttributes: B3 bitWillDetach                   */          \
85                 /*               B2 bitManifestationTolerant        */          \
86                 /*               B1 bitCanUpload, B0 bitCanDnload   */          \
87     0xE8, 0x03, /* wDetachTimeOut: 0x03E8 (1000) */                             \
88     UX_W0(UX_SLAVE_REQUEST_CONTROL_MAX_LENGTH),                                 \
89     UX_W1(UX_SLAVE_REQUEST_CONTROL_MAX_LENGTH), /* wTransferSize:   */          \
90     0x00, 0x01, /* bcdDFUVersion:  0x0100  */
91 
92 /* Interface descriptor for APP/DFU mode.  */
93 #define DFU_INTERFACE_DESCRIPTOR(bInterfaceNumber, bInterfaceProtocol)          \
94     /* Interface descriptor for DFU.  */                                        \
95     0x09, 0x04,                                                                 \
96     (bInterfaceNumber), 0x00, 0x00,                                             \
97     0xFE, 0x01, (bInterfaceProtocol),                                           \
98     0x00,                                                                       \
99 
100 #define DEVICE_FRAMEWORK_LENGTH_FULL_SPEED sizeof(device_framework_full_speed)
101 static UCHAR device_framework_full_speed[] = {
102 
103     /* Device descriptor */
104     0x12, 0x01, 0x10, 0x01, 0x00, 0x00, 0x00, 0x40,
105     0x99, 0x99, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02,
106     0x03, 0x01,
107 
108     /* Configuration descriptor */
109     0x09, 0x02, 0x1b, 0x00, 0x01, 0x01, 0x00, 0xc0,
110     0x32,
111 
112     /* Interface descriptor for DFU (bInterfaceProtocol = 1).  */
113     DFU_INTERFACE_DESCRIPTOR(0x00, 0x01)
114     DFU_FUNCTION_DESCRIPTOR
115 };
116 
117 #define DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED sizeof(device_framework_high_speed)
118 static UCHAR device_framework_high_speed[] = {
119 
120     /* Device descriptor */
121     0x12, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
122     0x99, 0x99, 0x00, 0x00, 0x01, 0x00, 0x01, 0x02,
123     0x03, 0x01,
124 
125     /* Device qualifier descriptor */
126     0x0a, 0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40,
127     0x01, 0x00,
128 
129     /* Configuration descriptor */
130     0x09, 0x02, 0x1b, 0x00, 0x01, 0x01, 0x00, 0xc0,
131     0x32,
132 
133     /* Interface descriptor for DFU (bInterfaceProtocol = 1).  */
134     DFU_INTERFACE_DESCRIPTOR(0x00, 0x01)
135     DFU_FUNCTION_DESCRIPTOR
136 };
137 
138 /* String Device Framework :
139     Byte 0 and 1 : Word containing the language ID : 0x0904 for US
140     Byte 2       : Byte containing the index of the descriptor
141     Byte 3       : Byte containing the length of the descriptor string
142 */
143 #define STRING_FRAMEWORK_LENGTH sizeof(string_framework)
144 static UCHAR string_framework[] = {
145 
146     /* Manufacturer string descriptor : Index 1 - "Microsoft AzureRTOS" */
147     0x09, 0x04, 0x01, 19,
148     'M', 'i', 'c', 'r', 'o', 's', 'o', 'f',
149     't', ' ', 'A', 'z', 'u', 'r', 'e', 'R',
150     'T', 'O', 'S',
151 
152     /* Product string descriptor : Index 2 - "DFU Demo Device" */
153     0x09, 0x04, 0x02, 15,
154     'D', 'F', 'U', ' ', 'D', 'e', 'm', 'o',
155     ' ', 'D', 'e', 'v', 'i', 'c', 'e',
156 
157     /* Serial Number string descriptor : Index 3 - "0000" */
158     0x09, 0x04, 0x03, 0x04,
159     '0', '0', '0', '0'
160 };
161 
162 /* Multiple languages are supported on the device, to add
163     a language besides english, the unicode language code must
164     be appended to the language_id_framework array and the length
165     adjusted accordingly. */
166 #define LANGUAGE_ID_FRAMEWORK_LENGTH sizeof(language_id_framework)
167 static UCHAR language_id_framework[] = {
168 
169     /* English. */
170     0x09, 0x04
171 };
172 
173 
174 #define DEVICE_FRAMEWORK_LENGTH_DFU sizeof(device_framework_dfu)
175 static UCHAR device_framework_dfu[] = {
176 
177     /* Device descriptor */
178     0x12, 0x01, 0x10, 0x01, 0x00, 0x00, 0x00, 0x40,
179     0x99, 0x99, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02,
180     0x03, 0x01,
181 
182     /* Configuration descriptor */
183     0x09, 0x02, 0x1B, 0x00, 0x01, 0x01, 0x00, 0xc0,
184     0x32,
185 
186     /* Interface descriptor for DFU (bInterfaceProtocol = 2).  */
187     DFU_INTERFACE_DESCRIPTOR(0x00, 0x02)
188     DFU_FUNCTION_DESCRIPTOR
189 };
190 
191 
192 /* Define the ISR dispatch.  */
193 
194 extern VOID    (*test_isr_dispatch)(void);
195 
196 
197 /* Prototype for test control return.  */
198 
199 void  test_control_return(UINT status);
200 
error_callback(UINT system_level,UINT system_context,UINT error_code)201 static VOID error_callback(UINT system_level, UINT system_context, UINT error_code)
202 {
203 
204     error_callback_counter ++;
205 
206     if (!error_callback_ignore)
207     {
208         {
209             /* Failed test.  */
210             printf("Error #%d, system_level: %d, system_context: %d, error_code: 0x%x\n", __LINE__, system_level, system_context, error_code);
211             test_control_return(1);
212         }
213     }
214 }
215 
216 
217 /* Define the ISR dispatch routine.  */
218 
test_isr(void)219 static void    test_isr(void)
220 {
221 
222     /* For further expansion of interrupt-level testing.  */
223 }
224 
225 
demo_system_host_change_function(ULONG event,UX_HOST_CLASS * cls,VOID * inst)226 static UINT demo_system_host_change_function(ULONG event, UX_HOST_CLASS *cls, VOID *inst)
227 {
228     if (event == UX_DEVICE_CONNECTION)
229     {
230         device = (UX_DEVICE *)inst;
231     }
232     if (event == UX_DEVICE_DISCONNECTION)
233     {
234         if ((VOID *)device == inst)
235             device = UX_NULL;
236     }
237 }
238 
239 
240 /* Define what the initial system looks like.  */
241 
242 #ifdef CTEST
test_application_define(void * first_unused_memory)243 void test_application_define(void *first_unused_memory)
244 #else
245 void    usbx_uxe_device_dfu_test_application_define(void *first_unused_memory)
246 #endif
247 {
248 
249 UINT                    status;
250 CHAR *                  stack_pointer;
251 CHAR *                  memory_pointer;
252 ULONG                   test_n;
253 
254     /* Inform user.  */
255     printf("Running uxe_device_dfu APIs Test.................................... ");
256 #if !defined(UX_DEVICE_CLASS_DFU_ENABLE_ERROR_CHECKING)
257 #warning Tests skipped due to compile option!
258     printf("SKIP SUCCESS!\n");
259     test_control_return(0);
260     return;
261 #endif /* UX_DEVICE_CLASS_DFU_ENABLE_ERROR_CHECKING */
262 
263 
264     /* Reset testing counts. */
265     ux_test_utility_sim_mutex_create_count_reset();
266     ux_test_utility_sim_sem_create_count_reset();
267     ux_test_utility_sim_sem_get_count_reset();
268     /* Reset error generations */
269     ux_test_utility_sim_sem_error_generation_stop();
270     ux_test_utility_sim_mutex_error_generation_stop();
271     ux_test_utility_sim_sem_get_error_generation_stop();
272 
273     /* Initialize the free memory pointer */
274     stack_pointer = (CHAR *) usbx_memory;
275     memory_pointer = stack_pointer + (UX_DEMO_STACK_SIZE * 2);
276 
277     /* Initialize USBX Memory */
278     status = ux_system_initialize(memory_pointer, UX_DEMO_MEMORY_SIZE, UX_NULL,0);
279 
280     /* Check for error.  */
281     if (status != UX_SUCCESS)
282     {
283 
284         printf("ERROR #%d\n", __LINE__);
285         test_control_return(1);
286     }
287 
288     /* Register the error callback. */
289     _ux_utility_error_callback_register(error_callback);
290 
291     /* The code below is required for installing the host portion of USBX */
292     status =  ux_host_stack_initialize(demo_system_host_change_function);
293     if (status != UX_SUCCESS)
294     {
295 
296         printf("ERROR #%d\n", __LINE__);
297         test_control_return(1);
298     }
299 
300     /* There is no host class for DFU now.  */
301 
302     /* The code below is required for installing the device portion of USBX. No call back for
303        device status change in this example. */
304     status =  ux_device_stack_initialize(device_framework_high_speed, DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED,
305                                        device_framework_full_speed, DEVICE_FRAMEWORK_LENGTH_FULL_SPEED,
306                                        string_framework, STRING_FRAMEWORK_LENGTH,
307                                        language_id_framework, LANGUAGE_ID_FRAMEWORK_LENGTH,UX_NULL);
308     if(status!=UX_SUCCESS)
309     {
310 
311         printf("ERROR #%d\n", __LINE__);
312         test_control_return(1);
313     }
314 
315     /* Store the DFU parameters.   */
316     dfu_parameter.ux_slave_class_dfu_parameter_instance_activate               =  demo_thread_dfu_activate;
317     dfu_parameter.ux_slave_class_dfu_parameter_instance_deactivate             =  demo_thread_dfu_deactivate;
318     dfu_parameter.ux_slave_class_dfu_parameter_read                            =  demo_thread_dfu_read;
319     dfu_parameter.ux_slave_class_dfu_parameter_write                           =  demo_thread_dfu_write;
320     dfu_parameter.ux_slave_class_dfu_parameter_get_status                      =  demo_thread_dfu_get_status;
321     dfu_parameter.ux_slave_class_dfu_parameter_notify                          =  demo_thread_dfu_notify;
322 #ifdef UX_DEVICE_CLASS_DFU_CUSTOM_REQUEST_ENABLE
323     dfu_parameter.ux_device_class_dfu_parameter_custom_request                 =  demo_thread_dfu_custom_request;
324 #endif
325     dfu_parameter.ux_slave_class_dfu_parameter_framework                       =  UX_NULL;
326     dfu_parameter.ux_slave_class_dfu_parameter_framework_length                =  DEVICE_FRAMEWORK_LENGTH_DFU;
327 
328     /* Initilize the device dfu class. The class is connected with interface 1 on configuration 1. */
329     // status =  ux_device_stack_class_register(_ux_system_slave_class_dfu_name, ux_device_class_dfu_entry,
330     //                                          1, 0, (VOID *)&dfu_parameter);
331     status =  ux_device_stack_class_register(_ux_system_slave_class_dfu_name, ux_device_class_dfu_entry,
332                                              1, 0, UX_NULL);
333     if(status != UX_INVALID_PARAMETER)
334     {
335 
336         printf("ERROR #%d\n", __LINE__);
337         test_control_return(1);
338     }
339 
340     status =  ux_device_stack_class_register(_ux_system_slave_class_dfu_name, ux_device_class_dfu_entry,
341                                              1, 0, (VOID *)&dfu_parameter);
342     if(status != UX_INVALID_PARAMETER)
343     {
344 
345         printf("ERROR #%d\n", __LINE__);
346         test_control_return(1);
347     }
348 
349     dfu_parameter.ux_slave_class_dfu_parameter_framework = device_framework_dfu;
350     status =  ux_device_stack_class_register(_ux_system_slave_class_dfu_name, ux_device_class_dfu_entry,
351                                              1, 0, (VOID *)&dfu_parameter);
352     if(status != UX_SUCCESS)
353     {
354 
355         printf("ERROR #%d\n", __LINE__);
356         test_control_return(1);
357     }
358 
359     /* Create the simulation thread.  */
360     status =  tx_thread_create(&ux_test_thread_simulation_0, "test simulation", ux_test_thread_simulation_0_entry, 0,
361             stack_pointer, UX_DEMO_STACK_SIZE,
362             20, 20, 1, TX_AUTO_START);
363 
364     /* Check for error.  */
365     if (status != TX_SUCCESS)
366     {
367 
368         printf("ERROR #%d\n", __LINE__);
369         test_control_return(1);
370     }
371 
372 }
373 
ux_test_thread_simulation_0_entry(ULONG arg)374 static void  ux_test_thread_simulation_0_entry(ULONG arg)
375 {
376     /* Sleep for a tick to make sure everything is complete.  */
377     tx_thread_sleep(1);
378 
379     /* Check for errors from other threads.  */
380     if (error_counter)
381     {
382 
383         /* Test error.  */
384         printf("ERROR #%d: total %ld errors\n", __LINE__, error_counter);
385         test_control_return(1);
386     }
387     else
388     {
389 
390         /* Successful test.  */
391         printf("SUCCESS!\n");
392         test_control_return(0);
393     }
394 }
395 
_req_DFU_LOCK(UX_TRANSFER * control_transfer)396 static UINT _req_DFU_LOCK(UX_TRANSFER *control_transfer)
397 {
398 UINT        status;
399 #if defined(UX_HOST_STANDALONE)
400     while(1)
401     {
402         ux_system_tasks_run();
403         tx_thread_relinquish();
404 
405         UX_ENDPOINT *endpoint = control_transfer -> ux_transfer_request_endpoint;
406         if (endpoint == UX_NULL || endpoint -> ux_endpoint_state != UX_ENDPOINT_RUNNING)
407         {
408             status = UX_ENDPOINT_HANDLE_UNKNOWN;
409             break;
410         }
411         UX_DEVICE *device = endpoint -> ux_endpoint_device;
412         if (device == UX_NULL || device -> ux_device_handle != (ULONG)(ALIGN_TYPE)(device))
413         {
414             status = UX_DEVICE_HANDLE_UNKNOWN;
415             break;
416         }
417         if ((device -> ux_device_flags & UX_DEVICE_FLAG_LOCK) == 0)
418         {
419             device -> ux_device_flags |= UX_DEVICE_FLAG_LOCK;
420             control_transfer -> ux_transfer_request_flags |= UX_TRANSFER_FLAG_AUTO_DEVICE_UNLOCK;
421             control_transfer -> ux_transfer_request_timeout_value = UX_WAIT_FOREVER;
422             status = UX_SUCCESS;
423             break;
424         }
425     }
426 #else
427     status = _ux_utility_semaphore_get(&control_transfer->ux_transfer_request_endpoint->ux_endpoint_device->ux_device_protection_semaphore, UX_WAIT_FOREVER);
428 #endif
429     if (status != UX_SUCCESS)
430     {
431         printf("ERROR #%d: %x\n", __LINE__, status);
432         test_control_return(1);
433     }
434 }
_req_DFU_GETSTATE(UX_TRANSFER * control_transfer)435 static UINT _req_DFU_GETSTATE(UX_TRANSFER *control_transfer)
436 {
437     _req_DFU_LOCK(control_transfer);
438     control_transfer->ux_transfer_request_type              = 0xA1;
439     control_transfer->ux_transfer_request_function          = UX_SLAVE_CLASS_DFU_COMMAND_GET_STATE;
440     control_transfer->ux_transfer_request_index             = 0;
441     control_transfer->ux_transfer_request_requested_length  = 1;
442     control_transfer->ux_transfer_request_data_pointer      = dfu_host_buffer;
443     control_transfer->ux_transfer_request_value             = 0;
444     return ux_host_stack_transfer_request(control_transfer);
445 }
_req_DFU_GETSTATUS(UX_TRANSFER * control_transfer)446 static UINT _req_DFU_GETSTATUS(UX_TRANSFER *control_transfer)
447 {
448     _req_DFU_LOCK(control_transfer);
449     control_transfer->ux_transfer_request_type              = 0xA1;
450     control_transfer->ux_transfer_request_function          = UX_SLAVE_CLASS_DFU_COMMAND_GET_STATUS;
451     control_transfer->ux_transfer_request_index             = 0;
452     control_transfer->ux_transfer_request_requested_length  = 6;
453     control_transfer->ux_transfer_request_data_pointer      = dfu_host_buffer;
454     control_transfer->ux_transfer_request_value             = 0;
455     return ux_host_stack_transfer_request(control_transfer);
456 }
_req_DFU_DETACH(UX_TRANSFER * control_transfer)457 static UINT _req_DFU_DETACH(UX_TRANSFER *control_transfer)
458 {
459     _req_DFU_LOCK(control_transfer);
460     control_transfer->ux_transfer_request_type              = 0x21;
461     control_transfer->ux_transfer_request_function          = UX_SLAVE_CLASS_DFU_COMMAND_DETACH;
462     control_transfer->ux_transfer_request_index             = 0;
463     control_transfer->ux_transfer_request_value             = 1000;
464     control_transfer->ux_transfer_request_requested_length  = 0;
465     return ux_host_stack_transfer_request(control_transfer);
466 }
_req_DFU_DNLOAD_IN(UX_TRANSFER * control_transfer,ULONG block,ULONG len)467 static UINT _req_DFU_DNLOAD_IN(UX_TRANSFER *control_transfer, ULONG block, ULONG len)
468 {
469     _req_DFU_LOCK(control_transfer);
470     control_transfer->ux_transfer_request_type              = 0xA1;
471     control_transfer->ux_transfer_request_function          = UX_SLAVE_CLASS_DFU_COMMAND_DOWNLOAD;
472     control_transfer->ux_transfer_request_index             = 0;
473     control_transfer->ux_transfer_request_data_pointer      = dfu_host_buffer;
474     control_transfer->ux_transfer_request_requested_length  = len;
475     control_transfer->ux_transfer_request_value             = block;
476     return ux_host_stack_transfer_request(control_transfer);
477 }
_req_DFU_DNLOAD(UX_TRANSFER * control_transfer,ULONG block,ULONG len)478 static UINT _req_DFU_DNLOAD(UX_TRANSFER *control_transfer, ULONG block, ULONG len)
479 {
480     _req_DFU_LOCK(control_transfer);
481     control_transfer->ux_transfer_request_type              = 0x21;
482     control_transfer->ux_transfer_request_function          = UX_SLAVE_CLASS_DFU_COMMAND_DOWNLOAD;
483     control_transfer->ux_transfer_request_index             = 0;
484     control_transfer->ux_transfer_request_data_pointer      = dfu_host_buffer;
485     control_transfer->ux_transfer_request_requested_length  = len;
486     control_transfer->ux_transfer_request_value             = block;
487     return ux_host_stack_transfer_request(control_transfer);
488 }
_req_DFU_UPLOAD(UX_TRANSFER * control_transfer,ULONG block,ULONG len)489 static UINT _req_DFU_UPLOAD(UX_TRANSFER *control_transfer, ULONG block, ULONG len)
490 {
491     _req_DFU_LOCK(control_transfer);
492     control_transfer->ux_transfer_request_type              = 0xA1;
493     control_transfer->ux_transfer_request_function          = UX_SLAVE_CLASS_DFU_COMMAND_UPLOAD;
494     control_transfer->ux_transfer_request_index             = 0;
495     control_transfer->ux_transfer_request_data_pointer      = dfu_host_buffer;
496     control_transfer->ux_transfer_request_requested_length  = len;
497     control_transfer->ux_transfer_request_value             = block;
498     return ux_host_stack_transfer_request(control_transfer);
499 }
_req_DFU_CLRSTATUS(UX_TRANSFER * control_transfer)500 static UINT _req_DFU_CLRSTATUS(UX_TRANSFER *control_transfer)
501 {
502     _req_DFU_LOCK(control_transfer);
503     control_transfer->ux_transfer_request_type              = 0x21;
504     control_transfer->ux_transfer_request_function          = UX_SLAVE_CLASS_DFU_COMMAND_CLEAR_STATUS;
505     control_transfer->ux_transfer_request_index             = 0;
506     control_transfer->ux_transfer_request_data_pointer      = UX_NULL;
507     control_transfer->ux_transfer_request_requested_length  = 0;
508     control_transfer->ux_transfer_request_value             = 0;
509     return ux_host_stack_transfer_request(control_transfer);
510 }
511 
512 
demo_device_state_change(ULONG event)513 static UINT    demo_device_state_change(ULONG event)
514 {
515     return(UX_SUCCESS);
516 }
517 
demo_thread_dfu_activate(VOID * dfu)518 static VOID    demo_thread_dfu_activate(VOID *dfu)
519 {
520 }
521 
demo_thread_dfu_deactivate(VOID * dfu)522 static VOID    demo_thread_dfu_deactivate(VOID *dfu)
523 {
524 }
525 
demo_thread_dfu_read(VOID * dfu,ULONG block_number,UCHAR * data_pointer,ULONG length,ULONG * actual_length)526 static UINT    demo_thread_dfu_read(VOID *dfu, ULONG block_number, UCHAR * data_pointer, ULONG length, ULONG *actual_length)
527 {
528 ULONG       return_length;
529 
530     stepinfo("dfuRead %ld,%ld: %2x %2x %2x %2x ... -> %p\n", block_number, length,
531         dfu_device_buffer[0], dfu_device_buffer[1], dfu_device_buffer[2], dfu_device_buffer[3],
532         data_pointer);
533     dfu_block = block_number;
534     dfu_transfer_length = length;
535 
536     return_length = UX_MIN(length, sizeof(dfu_device_buffer));
537     return_length = UX_MIN(return_length, dfu_actual_length);
538 
539     ux_utility_memory_copy(data_pointer, dfu_device_buffer, return_length);
540 
541     /* Here is where the data block is read from the firmware.  */
542     /* Some code needs to be inserted specifically for a target platform.  */
543     *actual_length =  return_length;
544     return(UX_SUCCESS);
545 }
546 
demo_thread_dfu_write(VOID * dfu,ULONG block_number,UCHAR * data_pointer,ULONG length,ULONG * media_status)547 static UINT    demo_thread_dfu_write(VOID *dfu, ULONG block_number, UCHAR * data_pointer, ULONG length, ULONG *media_status)
548 {
549     stepinfo("dfuWrite %ld,%ld\n", block_number, length);
550     dfu_block = block_number;
551     dfu_transfer_length = length;
552     ux_utility_memory_copy(dfu_device_buffer, data_pointer, UX_MIN(length, sizeof(dfu_device_buffer)));
553 
554     /* Here is where the data block is coming to be written to the firmware.  */
555     /* Some code needs to be inserted specifically for a target platform.  */
556     /* Return media status ok.  */
557     *media_status =  UX_SLAVE_CLASS_DFU_MEDIA_STATUS_OK    ;
558     return(UX_SUCCESS);
559 }
560 
demo_thread_dfu_get_status(VOID * dfu,ULONG * media_status)561 static UINT    demo_thread_dfu_get_status(VOID *dfu, ULONG *media_status)
562 {
563 
564     /* Return media status ok.  */
565     *media_status =  UX_SLAVE_CLASS_DFU_MEDIA_STATUS_OK    ;
566 
567     return(UX_SUCCESS);
568 }
569 
demo_thread_dfu_notify(VOID * dfu,ULONG notification)570 static UINT    demo_thread_dfu_notify(VOID *dfu, ULONG notification)
571 {
572     stepinfo("dfuNotify 0x%lx\n", notification);
573     switch (notification)
574     {
575 
576 
577         case    UX_SLAVE_CLASS_DFU_NOTIFICATION_BEGIN_DOWNLOAD        :
578 
579             /* Begin of Download. */
580             break;
581 
582         case    UX_SLAVE_CLASS_DFU_NOTIFICATION_END_DOWNLOAD        :
583 
584             /* Completion of Download. */
585             break;
586 
587         case    UX_SLAVE_CLASS_DFU_NOTIFICATION_ABORT_DOWNLOAD        :
588 
589             /* Download was aborted. */
590             break;
591 
592         case    UX_SLAVE_CLASS_DFU_NOTIFICATION_BEGIN_UPLOAD        :
593 
594             /* Begin of UPLOAD. */
595             break;
596 
597         case    UX_SLAVE_CLASS_DFU_NOTIFICATION_END_UPLOAD        :
598 
599             /* Completion of UPLOAD. */
600             break;
601 
602         case    UX_SLAVE_CLASS_DFU_NOTIFICATION_ABORT_UPLOAD        :
603 
604             /* Download was aborted. */
605             break;
606 
607         default :
608 
609             /* Bad notification signal. Should never get here.  */
610             break;
611 
612     }
613 
614     return(UX_SUCCESS);
615 }
616 
demo_thread_dfu_custom_request(VOID * dfu,UX_SLAVE_TRANSFER * transfer)617 static UINT demo_thread_dfu_custom_request(VOID *dfu, UX_SLAVE_TRANSFER *transfer)
618 {
619 UCHAR      *setup;
620 UCHAR      *buffer;
621 
622     /* Check state and request to insert custom operation, before the standard
623        handling process.
624        If no standard handling process is needed, return UX_SUCCESS.
625     */
626 
627    /* E.g., accept DNLOAD command with wLength 0 in dfuIDLE.  */
628    if (ux_device_class_dfu_state_get((UX_SLAVE_CLASS_DFU *)dfu) == UX_SLAVE_CLASS_DFU_STATUS_STATE_DFU_IDLE)
629    {
630        setup = transfer -> ux_slave_transfer_request_setup;
631        buffer = transfer -> ux_slave_transfer_request_data_pointer;
632 
633         if (setup[UX_SETUP_REQUEST] == UX_SLAVE_CLASS_DFU_COMMAND_DOWNLOAD &&
634             setup[UX_SETUP_LENGTH] == 0 &&
635             setup[UX_SETUP_LENGTH + 1] == 0)
636         {
637 
638             /* Accept the case (by default it's stalled).  */
639             stepinfo("dfuIDLE - accept dfuDNLOAD & wLength 0\n");
640 
641             /* Fill the status data payload.  First with status.  */
642             *buffer = UX_SLAVE_CLASS_DFU_STATUS_OK;
643 
644             /* Poll time out value is set to 500ms.  */
645             *(buffer + UX_SLAVE_CLASS_DFU_GET_STATUS_POLL_TIMEOUT) = UX_DW0(500);
646             *(buffer + UX_SLAVE_CLASS_DFU_GET_STATUS_POLL_TIMEOUT + 1) = UX_DW1(500);
647             *(buffer + UX_SLAVE_CLASS_DFU_GET_STATUS_POLL_TIMEOUT + 2) = UX_DW2(500);
648 
649             /* Next state: still dfuIDLE.  */
650             *(buffer + UX_SLAVE_CLASS_DFU_GET_STATUS_STATE) = (UCHAR) UX_SYSTEM_DFU_STATE_DFU_IDLE;
651 
652             /* String index set to 0.  */
653             *(buffer + UX_SLAVE_CLASS_DFU_GET_STATUS_STRING) = 0;
654 
655             /* We have a request to obtain the status of the DFU instance. */
656             _ux_device_stack_transfer_request(transfer, UX_SLAVE_CLASS_DFU_GET_STATUS_LENGTH, UX_SLAVE_CLASS_DFU_GET_STATUS_LENGTH);
657 
658             /* Inform stack it's taken.  */
659             return(UX_SUCCESS);
660         }
661     }
662 
663     /* No custom request.  */
664     return(UX_ERROR);
665 }
666