1 // SPDX-License-Identifier: GPL-2.0+
3 * f_sdp.c -- USB HID Serial Download Protocol
5 * Copyright (C) 2017 Toradex
6 * Author: Stefan Agner <stefan.agner@toradex.com>
8 * This file implements the Serial Download Protocol (SDP) as specified in
9 * the i.MX 6 Reference Manual. The SDP is a USB HID based protocol and
10 * allows to download images directly to memory. The implementation
11 * works with the imx_loader (imx_usb) USB client software on host side.
13 * Not all commands are implemented, e.g. WRITE_REGISTER, DCD_WRITE and
14 * SKIP_DCD_HEADER are only stubs.
16 * Parts of the implementation are based on f_dfu and f_thor.
25 #include <linux/printk.h>
27 #include <linux/usb/ch9.h>
28 #include <linux/usb/gadget.h>
29 #include <linux/usb/composite.h>
37 #include <imx_container.h>
40 #define HID_REPORT_ID_MASK 0x000000ff
45 #define HID_REQ_GET_REPORT 0x01
46 #define HID_REQ_GET_IDLE 0x02
47 #define HID_REQ_GET_PROTOCOL 0x03
48 #define HID_REQ_SET_REPORT 0x09
49 #define HID_REQ_SET_IDLE 0x0A
50 #define HID_REQ_SET_PROTOCOL 0x0B
52 #define HID_USAGE_PAGE_LEN 76
55 u8 usage_page
[HID_USAGE_PAGE_LEN
];
58 #define SDP_READ_REGISTER 0x0101
59 #define SDP_WRITE_REGISTER 0x0202
60 #define SDP_WRITE_FILE 0x0404
61 #define SDP_ERROR_STATUS 0x0505
62 #define SDP_DCD_WRITE 0x0a0a
63 #define SDP_JUMP_ADDRESS 0x0b0b
64 #define SDP_SKIP_DCD_HEADER 0x0c0c
66 #define SDP_SECURITY_CLOSED 0x12343412
67 #define SDP_SECURITY_OPEN 0x56787856
69 #define SDP_WRITE_FILE_COMPLETE 0x88888888
70 #define SDP_WRITE_REGISTER_COMPLETE 0x128A8A12
71 #define SDP_SKIP_DCD_HEADER_COMPLETE 0x900DD009
72 #define SDP_ERROR_IMXHEADER 0x000a0533
74 #define SDP_COMMAND_LEN 16
76 #define SDP_HID_PACKET_SIZE_EP1 1024
92 SDP_STATE_RX_DCD_DATA
,
93 SDP_STATE_RX_FILE_DATA
,
94 SDP_STATE_RX_FILE_DATA_BUSY
,
95 SDP_STATE_TX_SEC_CONF
,
96 SDP_STATE_TX_SEC_CONF_BUSY
,
97 SDP_STATE_TX_REGISTER
,
98 SDP_STATE_TX_REGISTER_BUSY
,
100 SDP_STATE_TX_STATUS_BUSY
,
105 struct usb_function usb_function
;
107 struct usb_descriptor_header
**function
;
110 enum sdp_state state
;
111 enum sdp_state next_state
;
114 u32 dnl_bytes_remaining
;
116 bool always_send_status
;
120 struct usb_request
*req
;
123 struct usb_ep
*in_ep
;
124 struct usb_request
*in_req
;
126 struct usb_ep
*out_ep
;
127 struct usb_request
*out_req
;
129 bool configuration_done
;
133 static struct f_sdp
*sdp_func
;
135 static inline struct f_sdp
*func_to_sdp(struct usb_function
*f
)
137 return container_of(f
, struct f_sdp
, usb_function
);
140 static struct usb_interface_descriptor sdp_intf_runtime
= {
141 .bLength
= sizeof(sdp_intf_runtime
),
142 .bDescriptorType
= USB_DT_INTERFACE
,
143 .bAlternateSetting
= 0,
145 .bInterfaceClass
= USB_CLASS_HID
,
146 .bInterfaceSubClass
= 0,
147 .bInterfaceProtocol
= 0,
148 /* .iInterface = DYNAMIC */
151 /* HID configuration */
152 static struct usb_class_hid_descriptor sdp_hid_desc
= {
153 .bLength
= sizeof(sdp_hid_desc
),
154 .bDescriptorType
= USB_DT_CS_DEVICE
,
156 .bcdCDC
= __constant_cpu_to_le16(0x0110),
158 .bNumDescriptors
= 1,
160 .bDescriptorType0
= USB_DT_HID_REPORT
,
161 .wDescriptorLength0
= HID_USAGE_PAGE_LEN
,
164 static struct usb_endpoint_descriptor in_desc
= {
165 .bLength
= USB_DT_ENDPOINT_SIZE
,
166 .bDescriptorType
= USB_DT_ENDPOINT
, /*USB_DT_CS_ENDPOINT*/
168 .bEndpointAddress
= 1 | USB_DIR_IN
,
169 .bmAttributes
= USB_ENDPOINT_XFER_INT
,
170 .wMaxPacketSize
= 64,
174 static struct usb_endpoint_descriptor out_desc
= {
175 .bLength
= USB_DT_ENDPOINT_SIZE
,
176 .bDescriptorType
= USB_DT_ENDPOINT
, /*USB_DT_CS_ENDPOINT*/
178 .bEndpointAddress
= 1 | USB_DIR_OUT
,
179 .bmAttributes
= USB_ENDPOINT_XFER_INT
,
180 .wMaxPacketSize
= 64,
184 static struct usb_endpoint_descriptor in_hs_desc
= {
185 .bLength
= USB_DT_ENDPOINT_SIZE
,
186 .bDescriptorType
= USB_DT_ENDPOINT
, /*USB_DT_CS_ENDPOINT*/
188 .bEndpointAddress
= 1 | USB_DIR_IN
,
189 .bmAttributes
= USB_ENDPOINT_XFER_INT
,
190 .wMaxPacketSize
= 512,
194 static struct usb_endpoint_descriptor out_hs_desc
= {
195 .bLength
= USB_DT_ENDPOINT_SIZE
,
196 .bDescriptorType
= USB_DT_ENDPOINT
, /*USB_DT_CS_ENDPOINT*/
198 .bEndpointAddress
= 1 | USB_DIR_OUT
,
199 .bmAttributes
= USB_ENDPOINT_XFER_INT
,
200 .wMaxPacketSize
= SDP_HID_PACKET_SIZE_EP1
,
204 static struct usb_descriptor_header
*sdp_runtime_descs
[] = {
205 (struct usb_descriptor_header
*)&sdp_intf_runtime
,
206 (struct usb_descriptor_header
*)&sdp_hid_desc
,
207 (struct usb_descriptor_header
*)&in_desc
,
208 (struct usb_descriptor_header
*)&out_desc
,
212 static struct usb_descriptor_header
*sdp_runtime_hs_descs
[] = {
213 (struct usb_descriptor_header
*)&sdp_intf_runtime
,
214 (struct usb_descriptor_header
*)&sdp_hid_desc
,
215 (struct usb_descriptor_header
*)&in_hs_desc
,
216 (struct usb_descriptor_header
*)&out_hs_desc
,
220 /* This is synchronized with what the SoC implementation reports */
221 static struct hid_report sdp_hid_report
= {
223 0x06, 0x00, 0xff, /* Usage Page */
224 0x09, 0x01, /* Usage (Pointer?) */
225 0xa1, 0x01, /* Collection */
227 0x85, 0x01, /* Report ID */
228 0x19, 0x01, /* Usage Minimum */
229 0x29, 0x01, /* Usage Maximum */
230 0x15, 0x00, /* Local Minimum */
231 0x26, 0xFF, 0x00, /* Local Maximum? */
232 0x75, 0x08, /* Report Size */
233 0x95, 0x10, /* Report Count */
234 0x91, 0x02, /* Output Data */
236 0x85, 0x02, /* Report ID */
237 0x19, 0x01, /* Usage Minimum */
238 0x29, 0x01, /* Usage Maximum */
239 0x15, 0x00, /* Local Minimum */
240 0x26, 0xFF, 0x00, /* Local Maximum? */
241 0x75, 0x80, /* Report Size 128 */
242 0x95, 0x40, /* Report Count */
243 0x91, 0x02, /* Output Data */
245 0x85, 0x03, /* Report ID */
246 0x19, 0x01, /* Usage Minimum */
247 0x29, 0x01, /* Usage Maximum */
248 0x15, 0x00, /* Local Minimum */
249 0x26, 0xFF, 0x00, /* Local Maximum? */
250 0x75, 0x08, /* Report Size 8 */
251 0x95, 0x04, /* Report Count */
252 0x81, 0x02, /* Input Data */
254 0x85, 0x04, /* Report ID */
255 0x19, 0x01, /* Usage Minimum */
256 0x29, 0x01, /* Usage Maximum */
257 0x15, 0x00, /* Local Minimum */
258 0x26, 0xFF, 0x00, /* Local Maximum? */
259 0x75, 0x08, /* Report Size 8 */
260 0x95, 0x40, /* Report Count */
261 0x81, 0x02, /* Input Data */
266 static const char sdp_name
[] = "Serial Downloader Protocol";
269 * static strings, in UTF-8
271 static struct usb_string strings_sdp_generic
[] = {
273 { } /* end of list */
276 static struct usb_gadget_strings stringtab_sdp_generic
= {
277 .language
= 0x0409, /* en-us */
278 .strings
= strings_sdp_generic
,
281 static struct usb_gadget_strings
*sdp_generic_strings
[] = {
282 &stringtab_sdp_generic
,
286 static inline void *sdp_ptr(u32 val
)
288 return (void *)(uintptr_t)val
;
291 static void sdp_rx_command_complete(struct usb_ep
*ep
, struct usb_request
*req
)
293 struct f_sdp
*sdp
= req
->context
;
294 int status
= req
->status
;
299 pr_err("Status: %d\n", status
);
304 pr_err("Unexpected report %d\n", report
);
308 struct sdp_command
*cmd
= req
->buf
+ 1;
310 debug("%s: command: %04x, addr: %08x, cnt: %u\n",
311 __func__
, be16_to_cpu(cmd
->cmd
),
312 be32_to_cpu(cmd
->addr
), be32_to_cpu(cmd
->cnt
));
314 switch (be16_to_cpu(cmd
->cmd
)) {
315 case SDP_READ_REGISTER
:
316 sdp
->always_send_status
= false;
317 sdp
->error_status
= 0x0;
319 sdp
->state
= SDP_STATE_TX_SEC_CONF
;
320 sdp
->dnl_address
= be32_to_cpu(cmd
->addr
);
321 sdp
->dnl_bytes_remaining
= be32_to_cpu(cmd
->cnt
);
322 sdp
->next_state
= SDP_STATE_TX_REGISTER
;
323 printf("Reading %d registers at 0x%08x... ",
324 sdp
->dnl_bytes_remaining
, sdp
->dnl_address
);
327 sdp
->always_send_status
= true;
328 sdp
->error_status
= SDP_WRITE_FILE_COMPLETE
;
330 sdp
->state
= SDP_STATE_RX_FILE_DATA
;
331 sdp
->dnl_address
= cmd
->addr
? be32_to_cpu(cmd
->addr
) : CONFIG_SDP_LOADADDR
;
332 sdp
->dnl_bytes_remaining
= be32_to_cpu(cmd
->cnt
);
333 sdp
->dnl_bytes
= sdp
->dnl_bytes_remaining
;
334 sdp
->next_state
= SDP_STATE_IDLE
;
336 printf("Downloading file of size %d to 0x%08x... ",
337 sdp
->dnl_bytes_remaining
, sdp
->dnl_address
);
340 case SDP_ERROR_STATUS
:
341 sdp
->always_send_status
= true;
342 sdp
->error_status
= 0;
344 sdp
->state
= SDP_STATE_TX_SEC_CONF
;
345 sdp
->next_state
= SDP_STATE_IDLE
;
348 sdp
->always_send_status
= true;
349 sdp
->error_status
= SDP_WRITE_REGISTER_COMPLETE
;
351 sdp
->state
= SDP_STATE_RX_DCD_DATA
;
352 sdp
->dnl_bytes_remaining
= be32_to_cpu(cmd
->cnt
);
353 sdp
->next_state
= SDP_STATE_IDLE
;
355 case SDP_JUMP_ADDRESS
:
356 sdp
->always_send_status
= false;
357 sdp
->error_status
= 0;
359 sdp
->jmp_address
= cmd
->addr
? be32_to_cpu(cmd
->addr
) : CONFIG_SDP_LOADADDR
;
360 sdp
->state
= SDP_STATE_TX_SEC_CONF
;
361 sdp
->next_state
= SDP_STATE_JUMP
;
363 case SDP_SKIP_DCD_HEADER
:
364 sdp
->always_send_status
= true;
365 sdp
->error_status
= SDP_SKIP_DCD_HEADER_COMPLETE
;
367 /* Ignore command, DCD not supported anyway */
368 sdp
->state
= SDP_STATE_TX_SEC_CONF
;
369 sdp
->next_state
= SDP_STATE_IDLE
;
372 pr_err("Unknown command: %04x\n", be16_to_cpu(cmd
->cmd
));
376 static void sdp_rx_data_complete(struct usb_ep
*ep
, struct usb_request
*req
)
378 struct f_sdp
*sdp
= req
->context
;
379 int status
= req
->status
;
382 int datalen
= req
->actual
- 1;
385 pr_err("Status: %d\n", status
);
390 pr_err("Unexpected report %d\n", report
);
394 if (sdp
->dnl_bytes_remaining
< datalen
) {
396 * Some USB stacks require to send a complete buffer as
397 * specified in the HID descriptor. This leads to longer
398 * transfers than the file length, no problem for us.
400 sdp
->dnl_bytes_remaining
= 0;
402 sdp
->dnl_bytes_remaining
-= datalen
;
405 if (sdp
->state
== SDP_STATE_RX_FILE_DATA_BUSY
) {
406 memcpy(sdp_ptr(sdp
->dnl_address
), req
->buf
+ 1, datalen
);
407 sdp
->dnl_address
+= datalen
;
410 if (sdp
->dnl_bytes_remaining
) {
411 sdp
->state
= SDP_STATE_RX_FILE_DATA
;
415 #ifndef CONFIG_SPL_BUILD
416 env_set_hex("filesize", sdp
->dnl_bytes
);
420 switch (sdp
->state
) {
421 case SDP_STATE_RX_FILE_DATA_BUSY
:
422 sdp
->state
= SDP_STATE_TX_SEC_CONF
;
424 case SDP_STATE_RX_DCD_DATA
:
425 sdp
->state
= SDP_STATE_TX_SEC_CONF
;
428 pr_err("Invalid state: %d\n", sdp
->state
);
432 static void sdp_tx_complete(struct usb_ep
*ep
, struct usb_request
*req
)
434 struct f_sdp
*sdp
= req
->context
;
435 int status
= req
->status
;
438 pr_err("Status: %d\n", status
);
442 switch (sdp
->state
) {
443 case SDP_STATE_TX_SEC_CONF_BUSY
:
444 /* Not all commands require status report */
445 if (sdp
->always_send_status
|| sdp
->error_status
)
446 sdp
->state
= SDP_STATE_TX_STATUS
;
448 sdp
->state
= sdp
->next_state
;
451 case SDP_STATE_TX_STATUS_BUSY
:
452 sdp
->state
= sdp
->next_state
;
454 case SDP_STATE_TX_REGISTER_BUSY
:
455 if (sdp
->dnl_bytes_remaining
)
456 sdp
->state
= SDP_STATE_TX_REGISTER
;
458 sdp
->state
= SDP_STATE_IDLE
;
461 pr_err("Wrong State: %d\n", sdp
->state
);
462 sdp
->state
= SDP_STATE_IDLE
;
465 debug("%s complete --> %d, %d/%d\n", ep
->name
,
466 status
, req
->actual
, req
->length
);
469 static int sdp_setup(struct usb_function
*f
, const struct usb_ctrlrequest
*ctrl
)
471 struct usb_gadget
*gadget
= f
->config
->cdev
->gadget
;
472 struct usb_request
*req
= f
->config
->cdev
->req
;
473 struct f_sdp
*sdp
= f
->config
->cdev
->req
->context
;
474 u16 len
= le16_to_cpu(ctrl
->wLength
);
475 u16 w_value
= le16_to_cpu(ctrl
->wValue
);
477 u8 req_type
= ctrl
->bRequestType
& USB_TYPE_MASK
;
479 debug("w_value: 0x%04x len: 0x%04x\n", w_value
, len
);
480 debug("req_type: 0x%02x ctrl->bRequest: 0x%02x sdp->state: %d\n",
481 req_type
, ctrl
->bRequest
, sdp
->state
);
483 if (req_type
== USB_TYPE_STANDARD
) {
484 if (ctrl
->bRequest
== USB_REQ_GET_DESCRIPTOR
) {
485 /* Send HID report descriptor */
486 value
= min(len
, (u16
) sizeof(sdp_hid_report
));
487 memcpy(req
->buf
, &sdp_hid_report
, value
);
488 sdp
->configuration_done
= true;
492 if (req_type
== USB_TYPE_CLASS
) {
493 int report
= w_value
& HID_REPORT_ID_MASK
;
495 /* HID (SDP) request */
496 switch (ctrl
->bRequest
) {
497 case HID_REQ_SET_REPORT
:
500 value
= SDP_COMMAND_LEN
+ 1;
501 req
->complete
= sdp_rx_command_complete
;
502 sdp_func
->ep_int_enable
= false;
506 req
->complete
= sdp_rx_data_complete
;
507 sdp_func
->state
= SDP_STATE_RX_FILE_DATA_BUSY
;
515 req
->zero
= value
< len
;
516 value
= usb_ep_queue(gadget
->ep0
, req
, 0);
518 debug("ep_queue --> %d\n", value
);
526 static int sdp_bind(struct usb_configuration
*c
, struct usb_function
*f
)
528 struct usb_gadget
*gadget
= c
->cdev
->gadget
;
529 struct usb_composite_dev
*cdev
= c
->cdev
;
530 struct f_sdp
*sdp
= func_to_sdp(f
);
533 id
= usb_interface_id(c
, f
);
536 sdp_intf_runtime
.bInterfaceNumber
= id
;
538 struct usb_ep
*ep_in
, *ep_out
;
540 /* allocate instance-specific endpoints */
541 ep_in
= usb_ep_autoconfig(gadget
, &in_desc
);
547 ep_out
= usb_ep_autoconfig(gadget
, &out_desc
);
553 if (gadget_is_dualspeed(gadget
)) {
554 /* Assume endpoint addresses are the same for both speeds */
555 in_hs_desc
.bEndpointAddress
= in_desc
.bEndpointAddress
;
556 out_hs_desc
.bEndpointAddress
= out_desc
.bEndpointAddress
;
559 sdp
->in_ep
= ep_in
; /* Store IN EP for enabling @ setup */
560 sdp
->out_ep
= ep_out
;
562 cdev
->req
->context
= sdp
;
568 static void sdp_unbind(struct usb_configuration
*c
, struct usb_function
*f
)
574 static struct usb_request
*alloc_ep_req(struct usb_ep
*ep
, unsigned length
)
576 struct usb_request
*req
;
578 req
= usb_ep_alloc_request(ep
, 0);
582 req
->length
= length
;
583 req
->buf
= memalign(CONFIG_SYS_CACHELINE_SIZE
, length
);
585 usb_ep_free_request(ep
, req
);
593 static struct usb_request
*sdp_start_ep(struct usb_ep
*ep
, bool in
)
595 struct usb_request
*req
;
598 req
= alloc_ep_req(ep
, 65);
600 req
= alloc_ep_req(ep
, 2048);
602 * OUT endpoint request length should be an integral multiple of
603 * maxpacket size 1024, else we break on certain controllers like
604 * DWC3 that expect bulk OUT requests to be divisible by maxpacket size.
606 debug("%s: ep:%p req:%p\n", __func__
, ep
, req
);
611 memset(req
->buf
, 0, req
->length
);
613 req
->complete
= sdp_tx_complete
;
615 req
->complete
= sdp_rx_command_complete
;
619 static int sdp_set_alt(struct usb_function
*f
, unsigned intf
, unsigned alt
)
621 struct f_sdp
*sdp
= func_to_sdp(f
);
622 struct usb_composite_dev
*cdev
= f
->config
->cdev
;
623 struct usb_gadget
*gadget
= cdev
->gadget
;
626 debug("%s: intf: %d alt: %d\n", __func__
, intf
, alt
);
628 if (gadget_is_dualspeed(gadget
) && gadget
->speed
== USB_SPEED_HIGH
) {
629 result
= usb_ep_enable(sdp
->in_ep
, &in_hs_desc
);
630 result
|= usb_ep_enable(sdp
->out_ep
, &out_hs_desc
);
632 result
= usb_ep_enable(sdp
->in_ep
, &in_desc
);
633 result
|= usb_ep_enable(sdp
->out_ep
, &out_desc
);
638 sdp
->in_req
= sdp_start_ep(sdp
->in_ep
, true);
639 sdp
->in_req
->context
= sdp
;
640 sdp
->out_req
= sdp_start_ep(sdp
->out_ep
, false);
641 sdp
->out_req
->context
= sdp
;
643 sdp
->in_ep
->driver_data
= cdev
; /* claim */
644 sdp
->out_ep
->driver_data
= cdev
; /* claim */
646 sdp
->altsetting
= alt
;
647 sdp
->state
= SDP_STATE_IDLE
;
648 sdp
->ep_int_enable
= true;
653 static int sdp_get_alt(struct usb_function
*f
, unsigned intf
)
655 struct f_sdp
*sdp
= func_to_sdp(f
);
657 return sdp
->altsetting
;
660 static void sdp_disable(struct usb_function
*f
)
662 struct f_sdp
*sdp
= func_to_sdp(f
);
664 usb_ep_disable(sdp
->in_ep
);
665 usb_ep_disable(sdp
->out_ep
);
668 free(sdp
->in_req
->buf
);
669 usb_ep_free_request(sdp
->in_ep
, sdp
->in_req
);
673 free(sdp
->out_req
->buf
);
674 usb_ep_free_request(sdp
->out_ep
, sdp
->out_req
);
679 static int sdp_bind_config(struct usb_configuration
*c
)
684 sdp_func
= memalign(CONFIG_SYS_CACHELINE_SIZE
, sizeof(*sdp_func
));
689 memset(sdp_func
, 0, sizeof(*sdp_func
));
691 sdp_func
->usb_function
.name
= "sdp";
692 sdp_func
->usb_function
.hs_descriptors
= sdp_runtime_hs_descs
;
693 sdp_func
->usb_function
.descriptors
= sdp_runtime_descs
;
694 sdp_func
->usb_function
.bind
= sdp_bind
;
695 sdp_func
->usb_function
.unbind
= sdp_unbind
;
696 sdp_func
->usb_function
.set_alt
= sdp_set_alt
;
697 sdp_func
->usb_function
.get_alt
= sdp_get_alt
;
698 sdp_func
->usb_function
.disable
= sdp_disable
;
699 sdp_func
->usb_function
.strings
= sdp_generic_strings
;
700 sdp_func
->usb_function
.setup
= sdp_setup
;
702 status
= usb_add_function(c
, &sdp_func
->usb_function
);
707 int sdp_init(struct udevice
*udc
)
709 printf("SDP: initialize...\n");
710 while (!sdp_func
->configuration_done
) {
712 puts("\rCTRL+C - Operation aborted.\n");
717 dm_usb_gadget_handle_interrupts(udc
);
723 static u32
sdp_jump_imxheader(void *address
)
725 flash_header_v2_t
*headerv2
= address
;
726 ulong (*entry
)(void);
728 if (headerv2
->header
.tag
!= IVT_HEADER_TAG
) {
729 printf("Header Tag is not an IMX image\n");
730 return SDP_ERROR_IMXHEADER
;
733 printf("Jumping to 0x%08x\n", headerv2
->entry
);
734 entry
= sdp_ptr(headerv2
->entry
);
737 /* The image probably never returns hence we won't reach that point */
741 #ifdef CONFIG_SPL_BUILD
742 static ulong
sdp_load_read(struct spl_load_info
*load
, ulong sector
,
743 ulong count
, void *buf
)
745 debug("%s: sector %lx, count %lx, buf %lx\n",
746 __func__
, sector
, count
, (ulong
)buf
);
747 memcpy(buf
, (void *)(load
->priv
+ sector
), count
);
751 static ulong
search_fit_header(ulong p
, int size
)
755 for (i
= 0; i
< size
; i
+= 4) {
756 if (genimg_get_format((const void *)(p
+ i
)) == IMAGE_FORMAT_FIT
)
763 static ulong
search_container_header(ulong p
, int size
)
768 for (i
= 0; i
< size
; i
+= 4) {
770 if (*(hdr
+ 3) == 0x87 && *hdr
== 0)
771 if (*(hdr
+ 1) != 0 || *(hdr
+ 2) != 0)
778 static int sdp_handle_in_ep(struct spl_image_info
*spl_image
,
779 struct spl_boot_device
*bootdev
)
781 u8
*data
= sdp_func
->in_req
->buf
;
785 switch (sdp_func
->state
) {
786 case SDP_STATE_TX_SEC_CONF
:
787 debug("Report 3: HAB security\n");
790 status
= SDP_SECURITY_OPEN
;
791 memcpy(&data
[1], &status
, 4);
792 sdp_func
->in_req
->length
= 5;
793 usb_ep_queue(sdp_func
->in_ep
, sdp_func
->in_req
, 0);
794 sdp_func
->state
= SDP_STATE_TX_SEC_CONF_BUSY
;
797 case SDP_STATE_TX_STATUS
:
798 debug("Report 4: Status\n");
801 memcpy(&data
[1], &sdp_func
->error_status
, 4);
802 sdp_func
->in_req
->length
= 65;
803 usb_ep_queue(sdp_func
->in_ep
, sdp_func
->in_req
, 0);
804 sdp_func
->state
= SDP_STATE_TX_STATUS_BUSY
;
806 case SDP_STATE_TX_REGISTER
:
807 debug("Report 4: Register Values\n");
810 datalen
= sdp_func
->dnl_bytes_remaining
;
815 memcpy(&data
[1], sdp_ptr(sdp_func
->dnl_address
), datalen
);
816 sdp_func
->in_req
->length
= 65;
818 sdp_func
->dnl_bytes_remaining
-= datalen
;
819 sdp_func
->dnl_address
+= datalen
;
821 usb_ep_queue(sdp_func
->in_ep
, sdp_func
->in_req
, 0);
822 sdp_func
->state
= SDP_STATE_TX_REGISTER_BUSY
;
825 printf("Jumping to header at 0x%08x\n", sdp_func
->jmp_address
);
826 status
= sdp_jump_imxheader(sdp_ptr(sdp_func
->jmp_address
));
828 /* If imx header fails, try some U-Boot specific headers */
830 #ifdef CONFIG_SPL_BUILD
831 if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER
))
832 sdp_func
->jmp_address
= (u32
)search_container_header((ulong
)sdp_func
->jmp_address
, sdp_func
->dnl_bytes
);
833 else if (IS_ENABLED(CONFIG_SPL_LOAD_FIT
))
834 sdp_func
->jmp_address
= (u32
)search_fit_header((ulong
)sdp_func
->jmp_address
, sdp_func
->dnl_bytes
);
835 if (sdp_func
->jmp_address
== 0)
836 panic("Error in search header, failed to jump\n");
838 printf("Found header at 0x%08x\n", sdp_func
->jmp_address
);
840 struct legacy_img_hdr
*header
=
841 sdp_ptr(sdp_func
->jmp_address
);
842 #ifdef CONFIG_SPL_LOAD_FIT
843 if (image_get_magic(header
) == FDT_MAGIC
) {
844 struct spl_load_info load
;
846 debug("Found FIT\n");
849 load
.read
= sdp_load_read
;
850 spl_load_simple_fit(spl_image
, &load
, 0,
856 if (IS_ENABLED(CONFIG_SPL_LOAD_IMX_CONTAINER
) &&
857 valid_container_hdr((void *)header
)) {
858 struct spl_load_info load
;
862 load
.read
= sdp_load_read
;
863 spl_load_imx_container(spl_image
, &load
, 0);
867 /* In SPL, allow jumps to U-Boot images */
868 struct spl_image_info spl_image
= {};
869 struct spl_boot_device bootdev
= {};
870 spl_parse_image_header(&spl_image
, &bootdev
, header
);
871 spl_board_prepare_for_boot();
872 jump_to_image_no_args(&spl_image
);
874 /* In U-Boot, allow jumps to scripts */
875 cmd_source_script(sdp_func
->jmp_address
, NULL
, NULL
);
879 sdp_func
->next_state
= SDP_STATE_IDLE
;
880 sdp_func
->error_status
= status
;
882 /* Only send Report 4 if there was an error */
884 sdp_func
->state
= SDP_STATE_TX_STATUS
;
886 sdp_func
->state
= SDP_STATE_IDLE
;
895 static void sdp_handle_out_ep(void)
899 if (sdp_func
->state
== SDP_STATE_IDLE
) {
900 sdp_func
->out_req
->complete
= sdp_rx_command_complete
;
901 rc
= usb_ep_queue(sdp_func
->out_ep
, sdp_func
->out_req
, 0);
903 printf("error in submission: %s\n",
904 sdp_func
->out_ep
->name
);
905 sdp_func
->state
= SDP_STATE_RX_CMD
;
906 } else if (sdp_func
->state
== SDP_STATE_RX_FILE_DATA
) {
907 sdp_func
->out_req
->complete
= sdp_rx_data_complete
;
908 rc
= usb_ep_queue(sdp_func
->out_ep
, sdp_func
->out_req
, 0);
910 printf("error in submission: %s\n",
911 sdp_func
->out_ep
->name
);
912 sdp_func
->state
= SDP_STATE_RX_FILE_DATA_BUSY
;
916 #ifndef CONFIG_SPL_BUILD
917 int sdp_handle(struct udevice
*udc
)
919 int spl_sdp_handle(struct udevice
*udc
, struct spl_image_info
*spl_image
,
920 struct spl_boot_device
*bootdev
)
924 printf("SDP: handle requests...\n");
927 puts("\rCTRL+C - Operation aborted.\n");
931 if (flag
== SDP_EXIT
)
935 dm_usb_gadget_handle_interrupts(udc
);
937 #ifdef CONFIG_SPL_BUILD
938 flag
= sdp_handle_in_ep(spl_image
, bootdev
);
940 flag
= sdp_handle_in_ep(NULL
, NULL
);
942 if (sdp_func
->ep_int_enable
)
947 int sdp_add(struct usb_configuration
*c
)
951 id
= usb_string_id(c
->cdev
);
954 strings_sdp_generic
[0].id
= id
;
955 sdp_intf_runtime
.iInterface
= id
;
957 debug("%s: cdev: %p gadget: %p gadget->ep0: %p\n", __func__
,
958 c
->cdev
, c
->cdev
->gadget
, c
->cdev
->gadget
->ep0
);
960 return sdp_bind_config(c
);
963 DECLARE_GADGET_BIND_CALLBACK(usb_dnl_sdp
, sdp_add
);