]> git.sur5r.net Git - u-boot/blobdiff - drivers/usb/gadget/f_fastboot.c
env: Rename getenv/_f() to env_get()
[u-boot] / drivers / usb / gadget / f_fastboot.c
index 79612318872c6fa2bf906851a9d706972f036ac0..d05b74b2d2afe2270e77d532a5ab459e7b785b90 100644 (file)
 #define TX_ENDPOINT_MAXIMUM_PACKET_SIZE      (0x0040)
 
 #define EP_BUFFER_SIZE                 4096
+/*
+ * EP_BUFFER_SIZE must always be an integral multiple of maxpacket size
+ * (64 or 512 or 1024), else we break on certain controllers like DWC3
+ * that expect bulk OUT requests to be divisible by maxpacket size.
+ */
 
 struct f_fastboot {
        struct usb_function usb_function;
@@ -54,10 +59,8 @@ static inline struct f_fastboot *func_to_fastboot(struct usb_function *f)
 }
 
 static struct f_fastboot *fastboot_func;
-static unsigned int fastboot_flash_session_id;
 static unsigned int download_size;
 static unsigned int download_bytes;
-static bool is_high_speed;
 
 static struct usb_endpoint_descriptor fs_ep_in = {
        .bLength            = USB_DT_ENDPOINT_SIZE,
@@ -148,16 +151,18 @@ static void rx_handler_command(struct usb_ep *ep, struct usb_request *req);
 static int strcmp_l1(const char *s1, const char *s2);
 
 
-void fastboot_fail(char *response, const char *reason)
+static char *fb_response_str;
+
+void fastboot_fail(const char *reason)
 {
-       strncpy(response, "FAIL\0", 5);
-       strncat(response, reason, FASTBOOT_RESPONSE_LEN - 4 - 1);
+       strncpy(fb_response_str, "FAIL\0", 5);
+       strncat(fb_response_str, reason, FASTBOOT_RESPONSE_LEN - 4 - 1);
 }
 
-void fastboot_okay(char *response, const char *reason)
+void fastboot_okay(const char *reason)
 {
-       strncpy(response, "OKAY\0", 5);
-       strncat(response, reason, FASTBOOT_RESPONSE_LEN - 4 - 1);
+       strncpy(fb_response_str, "OKAY\0", 5);
+       strncat(fb_response_str, reason, FASTBOOT_RESPONSE_LEN - 4 - 1);
 }
 
 static void fastboot_complete(struct usb_ep *ep, struct usb_request *req)
@@ -207,7 +212,7 @@ static int fastboot_bind(struct usb_configuration *c, struct usb_function *f)
                f->hs_descriptors = fb_hs_function;
        }
 
-       s = getenv("serial#");
+       s = env_get("serial#");
        if (s)
                g_dnl_set_serialnumber((char *)s);
 
@@ -269,11 +274,6 @@ static int fastboot_set_alt(struct usb_function *f,
        debug("%s: func: %s intf: %d alt: %d\n",
              __func__, f->name, interface, alt);
 
-       if (gadget->speed == USB_SPEED_HIGH)
-               is_high_speed = true;
-       else
-               is_high_speed = false;
-
        d = fb_ep_desc(gadget, &fs_ep_out, &hs_ep_out);
        ret = usb_ep_enable(f_fb->out_ep, d);
        if (ret) {
@@ -425,50 +425,56 @@ static void cb_getvar(struct usb_ep *ep, struct usb_request *req)
 
                sprintf(str_num, "0x%08x", CONFIG_FASTBOOT_BUF_SIZE);
                strncat(response, str_num, chars_left);
-
-               /*
-                * This also indicates the start of a new flashing
-                * "session", in which we could have 1-N buffers to
-                * write to a partition.
-                *
-                * Reset our session counter.
-                */
-               fastboot_flash_session_id = 0;
        } else if (!strcmp_l1("serialno", cmd)) {
-               s = getenv("serial#");
+               s = env_get("serial#");
                if (s)
                        strncat(response, s, chars_left);
                else
                        strcpy(response, "FAILValue not set");
        } else {
-               char envstr[32];
+               char *envstr;
+
+               envstr = malloc(strlen("fastboot.") + strlen(cmd) + 1);
+               if (!envstr) {
+                       fastboot_tx_write_str("FAILmalloc error");
+                       return;
+               }
 
-               snprintf(envstr, sizeof(envstr) - 1, "fastboot.%s", cmd);
-               s = getenv(envstr);
+               sprintf(envstr, "fastboot.%s", cmd);
+               s = env_get(envstr);
                if (s) {
                        strncat(response, s, chars_left);
                } else {
                        printf("WARNING: unknown variable: %s\n", cmd);
                        strcpy(response, "FAILVariable not implemented");
                }
+
+               free(envstr);
        }
        fastboot_tx_write_str(response);
 }
 
-static unsigned int rx_bytes_expected(unsigned int maxpacket)
+static unsigned int rx_bytes_expected(struct usb_ep *ep)
 {
        int rx_remain = download_size - download_bytes;
-       int rem = 0;
-       if (rx_remain < 0)
+       unsigned int rem;
+       unsigned int maxpacket = ep->maxpacket;
+
+       if (rx_remain <= 0)
                return 0;
-       if (rx_remain > EP_BUFFER_SIZE)
+       else if (rx_remain > EP_BUFFER_SIZE)
                return EP_BUFFER_SIZE;
-       if (rx_remain < maxpacket) {
-               rx_remain = maxpacket;
-       } else if (rx_remain % maxpacket != 0) {
-               rem = rx_remain % maxpacket;
+
+       /*
+        * Some controllers e.g. DWC3 don't like OUT transfers to be
+        * not ending in maxpacket boundary. So just make them happy by
+        * always requesting for integral multiple of maxpackets.
+        * This shouldn't bother controllers that don't care about it.
+        */
+       rem = rx_remain % maxpacket;
+       if (rem > 0)
                rx_remain = rx_remain + (maxpacket - rem);
-       }
+
        return rx_remain;
 }
 
@@ -480,7 +486,6 @@ static void rx_handler_dl_image(struct usb_ep *ep, struct usb_request *req)
        const unsigned char *buffer = req->buf;
        unsigned int buffer_size = req->actual;
        unsigned int pre_dot_num, now_dot_num;
-       unsigned int max;
 
        if (req->status != 0) {
                printf("Bad status: %d\n", req->status);
@@ -518,11 +523,7 @@ static void rx_handler_dl_image(struct usb_ep *ep, struct usb_request *req)
 
                printf("\ndownloading of %d bytes finished\n", download_bytes);
        } else {
-               max = is_high_speed ? hs_ep_out.wMaxPacketSize :
-                               fs_ep_out.wMaxPacketSize;
-               req->length = rx_bytes_expected(max);
-               if (req->length < ep->maxpacket)
-                       req->length = ep->maxpacket;
+               req->length = rx_bytes_expected(ep);
        }
 
        req->actual = 0;
@@ -533,7 +534,6 @@ static void cb_download(struct usb_ep *ep, struct usb_request *req)
 {
        char *cmd = req->buf;
        char response[FASTBOOT_RESPONSE_LEN];
-       unsigned int max;
 
        strsep(&cmd, ":");
        download_size = simple_strtoul(cmd, NULL, 16);
@@ -549,11 +549,7 @@ static void cb_download(struct usb_ep *ep, struct usb_request *req)
        } else {
                sprintf(response, "DATA%08x", download_size);
                req->complete = rx_handler_dl_image;
-               max = is_high_speed ? hs_ep_out.wMaxPacketSize :
-                       fs_ep_out.wMaxPacketSize;
-               req->length = rx_bytes_expected(max);
-               if (req->length < ep->maxpacket)
-                       req->length = ep->maxpacket;
+               req->length = rx_bytes_expected(ep);
        }
        fastboot_tx_write_str(response);
 }
@@ -602,18 +598,19 @@ static void cb_flash(struct usb_ep *ep, struct usb_request *req)
                return;
        }
 
-       strcpy(response, "FAILno flash device defined");
+       /* initialize the response buffer */
+       fb_response_str = response;
+
+       fastboot_fail("no flash device defined");
 #ifdef CONFIG_FASTBOOT_FLASH_MMC_DEV
-       fb_mmc_flash_write(cmd, fastboot_flash_session_id,
-                          (void *)CONFIG_FASTBOOT_BUF_ADDR,
-                          download_bytes, response);
+       fb_mmc_flash_write(cmd, (void *)CONFIG_FASTBOOT_BUF_ADDR,
+                          download_bytes);
 #endif
 #ifdef CONFIG_FASTBOOT_FLASH_NAND_DEV
-       fb_nand_flash_write(cmd, fastboot_flash_session_id,
+       fb_nand_flash_write(cmd,
                            (void *)CONFIG_FASTBOOT_BUF_ADDR,
-                           download_bytes, response);
+                           download_bytes);
 #endif
-       fastboot_flash_session_id++;
        fastboot_tx_write_str(response);
 }
 #endif
@@ -653,13 +650,15 @@ static void cb_erase(struct usb_ep *ep, struct usb_request *req)
                return;
        }
 
-       strcpy(response, "FAILno flash device defined");
+       /* initialize the response buffer */
+       fb_response_str = response;
 
+       fastboot_fail("no flash device defined");
 #ifdef CONFIG_FASTBOOT_FLASH_MMC_DEV
-       fb_mmc_erase(cmd, response);
+       fb_mmc_erase(cmd);
 #endif
 #ifdef CONFIG_FASTBOOT_FLASH_NAND_DEV
-       fb_nand_erase(cmd, response);
+       fb_nand_erase(cmd);
 #endif
        fastboot_tx_write_str(response);
 }