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