1*bf2b72beSEddie Cai /* 2*bf2b72beSEddie Cai * (C) Copyright 2017 3*bf2b72beSEddie Cai * 4*bf2b72beSEddie Cai * Eddie Cai <eddie.cai.linux@gmail.com> 5*bf2b72beSEddie Cai * 6*bf2b72beSEddie Cai * SPDX-License-Identifier: GPL-2.0+ 7*bf2b72beSEddie Cai */ 8*bf2b72beSEddie Cai #include <config.h> 9*bf2b72beSEddie Cai #include <common.h> 10*bf2b72beSEddie Cai #include <errno.h> 11*bf2b72beSEddie Cai #include <malloc.h> 12*bf2b72beSEddie Cai #include <memalign.h> 13*bf2b72beSEddie Cai #include <linux/usb/ch9.h> 14*bf2b72beSEddie Cai #include <linux/usb/gadget.h> 15*bf2b72beSEddie Cai #include <linux/usb/composite.h> 16*bf2b72beSEddie Cai #include <linux/compiler.h> 17*bf2b72beSEddie Cai #include <version.h> 18*bf2b72beSEddie Cai #include <g_dnl.h> 19*bf2b72beSEddie Cai #include <asm/arch/f_rockusb.h> 20*bf2b72beSEddie Cai 21*bf2b72beSEddie Cai static inline struct f_rockusb *func_to_rockusb(struct usb_function *f) 22*bf2b72beSEddie Cai { 23*bf2b72beSEddie Cai return container_of(f, struct f_rockusb, usb_function); 24*bf2b72beSEddie Cai } 25*bf2b72beSEddie Cai 26*bf2b72beSEddie Cai static struct usb_endpoint_descriptor fs_ep_in = { 27*bf2b72beSEddie Cai .bLength = USB_DT_ENDPOINT_SIZE, 28*bf2b72beSEddie Cai .bDescriptorType = USB_DT_ENDPOINT, 29*bf2b72beSEddie Cai .bEndpointAddress = USB_DIR_IN, 30*bf2b72beSEddie Cai .bmAttributes = USB_ENDPOINT_XFER_BULK, 31*bf2b72beSEddie Cai .wMaxPacketSize = cpu_to_le16(64), 32*bf2b72beSEddie Cai }; 33*bf2b72beSEddie Cai 34*bf2b72beSEddie Cai static struct usb_endpoint_descriptor fs_ep_out = { 35*bf2b72beSEddie Cai .bLength = USB_DT_ENDPOINT_SIZE, 36*bf2b72beSEddie Cai .bDescriptorType = USB_DT_ENDPOINT, 37*bf2b72beSEddie Cai .bEndpointAddress = USB_DIR_OUT, 38*bf2b72beSEddie Cai .bmAttributes = USB_ENDPOINT_XFER_BULK, 39*bf2b72beSEddie Cai .wMaxPacketSize = cpu_to_le16(64), 40*bf2b72beSEddie Cai }; 41*bf2b72beSEddie Cai 42*bf2b72beSEddie Cai static struct usb_endpoint_descriptor hs_ep_in = { 43*bf2b72beSEddie Cai .bLength = USB_DT_ENDPOINT_SIZE, 44*bf2b72beSEddie Cai .bDescriptorType = USB_DT_ENDPOINT, 45*bf2b72beSEddie Cai .bEndpointAddress = USB_DIR_IN, 46*bf2b72beSEddie Cai .bmAttributes = USB_ENDPOINT_XFER_BULK, 47*bf2b72beSEddie Cai .wMaxPacketSize = cpu_to_le16(512), 48*bf2b72beSEddie Cai }; 49*bf2b72beSEddie Cai 50*bf2b72beSEddie Cai static struct usb_endpoint_descriptor hs_ep_out = { 51*bf2b72beSEddie Cai .bLength = USB_DT_ENDPOINT_SIZE, 52*bf2b72beSEddie Cai .bDescriptorType = USB_DT_ENDPOINT, 53*bf2b72beSEddie Cai .bEndpointAddress = USB_DIR_OUT, 54*bf2b72beSEddie Cai .bmAttributes = USB_ENDPOINT_XFER_BULK, 55*bf2b72beSEddie Cai .wMaxPacketSize = cpu_to_le16(512), 56*bf2b72beSEddie Cai }; 57*bf2b72beSEddie Cai 58*bf2b72beSEddie Cai static struct usb_interface_descriptor interface_desc = { 59*bf2b72beSEddie Cai .bLength = USB_DT_INTERFACE_SIZE, 60*bf2b72beSEddie Cai .bDescriptorType = USB_DT_INTERFACE, 61*bf2b72beSEddie Cai .bInterfaceNumber = 0x00, 62*bf2b72beSEddie Cai .bAlternateSetting = 0x00, 63*bf2b72beSEddie Cai .bNumEndpoints = 0x02, 64*bf2b72beSEddie Cai .bInterfaceClass = ROCKUSB_INTERFACE_CLASS, 65*bf2b72beSEddie Cai .bInterfaceSubClass = ROCKUSB_INTERFACE_SUB_CLASS, 66*bf2b72beSEddie Cai .bInterfaceProtocol = ROCKUSB_INTERFACE_PROTOCOL, 67*bf2b72beSEddie Cai }; 68*bf2b72beSEddie Cai 69*bf2b72beSEddie Cai static struct usb_descriptor_header *rkusb_fs_function[] = { 70*bf2b72beSEddie Cai (struct usb_descriptor_header *)&interface_desc, 71*bf2b72beSEddie Cai (struct usb_descriptor_header *)&fs_ep_in, 72*bf2b72beSEddie Cai (struct usb_descriptor_header *)&fs_ep_out, 73*bf2b72beSEddie Cai }; 74*bf2b72beSEddie Cai 75*bf2b72beSEddie Cai static struct usb_descriptor_header *rkusb_hs_function[] = { 76*bf2b72beSEddie Cai (struct usb_descriptor_header *)&interface_desc, 77*bf2b72beSEddie Cai (struct usb_descriptor_header *)&hs_ep_in, 78*bf2b72beSEddie Cai (struct usb_descriptor_header *)&hs_ep_out, 79*bf2b72beSEddie Cai NULL, 80*bf2b72beSEddie Cai }; 81*bf2b72beSEddie Cai 82*bf2b72beSEddie Cai static const char rkusb_name[] = "Rockchip Rockusb"; 83*bf2b72beSEddie Cai 84*bf2b72beSEddie Cai static struct usb_string rkusb_string_defs[] = { 85*bf2b72beSEddie Cai [0].s = rkusb_name, 86*bf2b72beSEddie Cai { } /* end of list */ 87*bf2b72beSEddie Cai }; 88*bf2b72beSEddie Cai 89*bf2b72beSEddie Cai static struct usb_gadget_strings stringtab_rkusb = { 90*bf2b72beSEddie Cai .language = 0x0409, /* en-us */ 91*bf2b72beSEddie Cai .strings = rkusb_string_defs, 92*bf2b72beSEddie Cai }; 93*bf2b72beSEddie Cai 94*bf2b72beSEddie Cai static struct usb_gadget_strings *rkusb_strings[] = { 95*bf2b72beSEddie Cai &stringtab_rkusb, 96*bf2b72beSEddie Cai NULL, 97*bf2b72beSEddie Cai }; 98*bf2b72beSEddie Cai 99*bf2b72beSEddie Cai static struct f_rockusb *rockusb_func; 100*bf2b72beSEddie Cai static void rx_handler_command(struct usb_ep *ep, struct usb_request *req); 101*bf2b72beSEddie Cai static int rockusb_tx_write_csw(u32 tag, int residue, u8 status, int size); 102*bf2b72beSEddie Cai 103*bf2b72beSEddie Cai struct f_rockusb *get_rkusb(void) 104*bf2b72beSEddie Cai { 105*bf2b72beSEddie Cai struct f_rockusb *f_rkusb = rockusb_func; 106*bf2b72beSEddie Cai 107*bf2b72beSEddie Cai if (!f_rkusb) { 108*bf2b72beSEddie Cai f_rkusb = memalign(CONFIG_SYS_CACHELINE_SIZE, sizeof(*f_rkusb)); 109*bf2b72beSEddie Cai if (!f_rkusb) 110*bf2b72beSEddie Cai return 0; 111*bf2b72beSEddie Cai 112*bf2b72beSEddie Cai rockusb_func = f_rkusb; 113*bf2b72beSEddie Cai memset(f_rkusb, 0, sizeof(*f_rkusb)); 114*bf2b72beSEddie Cai } 115*bf2b72beSEddie Cai 116*bf2b72beSEddie Cai if (!f_rkusb->buf_head) { 117*bf2b72beSEddie Cai f_rkusb->buf_head = memalign(CONFIG_SYS_CACHELINE_SIZE, 118*bf2b72beSEddie Cai RKUSB_BUF_SIZE); 119*bf2b72beSEddie Cai if (!f_rkusb->buf_head) 120*bf2b72beSEddie Cai return 0; 121*bf2b72beSEddie Cai 122*bf2b72beSEddie Cai f_rkusb->buf = f_rkusb->buf_head; 123*bf2b72beSEddie Cai memset(f_rkusb->buf_head, 0, RKUSB_BUF_SIZE); 124*bf2b72beSEddie Cai } 125*bf2b72beSEddie Cai return f_rkusb; 126*bf2b72beSEddie Cai } 127*bf2b72beSEddie Cai 128*bf2b72beSEddie Cai static struct usb_endpoint_descriptor *rkusb_ep_desc( 129*bf2b72beSEddie Cai struct usb_gadget *g, 130*bf2b72beSEddie Cai struct usb_endpoint_descriptor *fs, 131*bf2b72beSEddie Cai struct usb_endpoint_descriptor *hs) 132*bf2b72beSEddie Cai { 133*bf2b72beSEddie Cai if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH) 134*bf2b72beSEddie Cai return hs; 135*bf2b72beSEddie Cai return fs; 136*bf2b72beSEddie Cai } 137*bf2b72beSEddie Cai 138*bf2b72beSEddie Cai static void rockusb_complete(struct usb_ep *ep, struct usb_request *req) 139*bf2b72beSEddie Cai { 140*bf2b72beSEddie Cai int status = req->status; 141*bf2b72beSEddie Cai 142*bf2b72beSEddie Cai if (!status) 143*bf2b72beSEddie Cai return; 144*bf2b72beSEddie Cai debug("status: %d ep '%s' trans: %d\n", status, ep->name, req->actual); 145*bf2b72beSEddie Cai } 146*bf2b72beSEddie Cai 147*bf2b72beSEddie Cai /* config the rockusb device*/ 148*bf2b72beSEddie Cai static int rockusb_bind(struct usb_configuration *c, struct usb_function *f) 149*bf2b72beSEddie Cai { 150*bf2b72beSEddie Cai int id; 151*bf2b72beSEddie Cai struct usb_gadget *gadget = c->cdev->gadget; 152*bf2b72beSEddie Cai struct f_rockusb *f_rkusb = func_to_rockusb(f); 153*bf2b72beSEddie Cai const char *s; 154*bf2b72beSEddie Cai 155*bf2b72beSEddie Cai id = usb_interface_id(c, f); 156*bf2b72beSEddie Cai if (id < 0) 157*bf2b72beSEddie Cai return id; 158*bf2b72beSEddie Cai interface_desc.bInterfaceNumber = id; 159*bf2b72beSEddie Cai 160*bf2b72beSEddie Cai id = usb_string_id(c->cdev); 161*bf2b72beSEddie Cai if (id < 0) 162*bf2b72beSEddie Cai return id; 163*bf2b72beSEddie Cai 164*bf2b72beSEddie Cai rkusb_string_defs[0].id = id; 165*bf2b72beSEddie Cai interface_desc.iInterface = id; 166*bf2b72beSEddie Cai 167*bf2b72beSEddie Cai f_rkusb->in_ep = usb_ep_autoconfig(gadget, &fs_ep_in); 168*bf2b72beSEddie Cai if (!f_rkusb->in_ep) 169*bf2b72beSEddie Cai return -ENODEV; 170*bf2b72beSEddie Cai f_rkusb->in_ep->driver_data = c->cdev; 171*bf2b72beSEddie Cai 172*bf2b72beSEddie Cai f_rkusb->out_ep = usb_ep_autoconfig(gadget, &fs_ep_out); 173*bf2b72beSEddie Cai if (!f_rkusb->out_ep) 174*bf2b72beSEddie Cai return -ENODEV; 175*bf2b72beSEddie Cai f_rkusb->out_ep->driver_data = c->cdev; 176*bf2b72beSEddie Cai 177*bf2b72beSEddie Cai f->descriptors = rkusb_fs_function; 178*bf2b72beSEddie Cai 179*bf2b72beSEddie Cai if (gadget_is_dualspeed(gadget)) { 180*bf2b72beSEddie Cai hs_ep_in.bEndpointAddress = fs_ep_in.bEndpointAddress; 181*bf2b72beSEddie Cai hs_ep_out.bEndpointAddress = fs_ep_out.bEndpointAddress; 182*bf2b72beSEddie Cai f->hs_descriptors = rkusb_hs_function; 183*bf2b72beSEddie Cai } 184*bf2b72beSEddie Cai 185*bf2b72beSEddie Cai s = env_get("serial#"); 186*bf2b72beSEddie Cai if (s) 187*bf2b72beSEddie Cai g_dnl_set_serialnumber((char *)s); 188*bf2b72beSEddie Cai 189*bf2b72beSEddie Cai return 0; 190*bf2b72beSEddie Cai } 191*bf2b72beSEddie Cai 192*bf2b72beSEddie Cai static void rockusb_unbind(struct usb_configuration *c, struct usb_function *f) 193*bf2b72beSEddie Cai { 194*bf2b72beSEddie Cai /* clear the configuration*/ 195*bf2b72beSEddie Cai memset(rockusb_func, 0, sizeof(*rockusb_func)); 196*bf2b72beSEddie Cai } 197*bf2b72beSEddie Cai 198*bf2b72beSEddie Cai static void rockusb_disable(struct usb_function *f) 199*bf2b72beSEddie Cai { 200*bf2b72beSEddie Cai struct f_rockusb *f_rkusb = func_to_rockusb(f); 201*bf2b72beSEddie Cai 202*bf2b72beSEddie Cai usb_ep_disable(f_rkusb->out_ep); 203*bf2b72beSEddie Cai usb_ep_disable(f_rkusb->in_ep); 204*bf2b72beSEddie Cai 205*bf2b72beSEddie Cai if (f_rkusb->out_req) { 206*bf2b72beSEddie Cai free(f_rkusb->out_req->buf); 207*bf2b72beSEddie Cai usb_ep_free_request(f_rkusb->out_ep, f_rkusb->out_req); 208*bf2b72beSEddie Cai f_rkusb->out_req = NULL; 209*bf2b72beSEddie Cai } 210*bf2b72beSEddie Cai if (f_rkusb->in_req) { 211*bf2b72beSEddie Cai free(f_rkusb->in_req->buf); 212*bf2b72beSEddie Cai usb_ep_free_request(f_rkusb->in_ep, f_rkusb->in_req); 213*bf2b72beSEddie Cai f_rkusb->in_req = NULL; 214*bf2b72beSEddie Cai } 215*bf2b72beSEddie Cai if (f_rkusb->buf_head) { 216*bf2b72beSEddie Cai free(f_rkusb->buf_head); 217*bf2b72beSEddie Cai f_rkusb->buf_head = NULL; 218*bf2b72beSEddie Cai f_rkusb->buf = NULL; 219*bf2b72beSEddie Cai } 220*bf2b72beSEddie Cai } 221*bf2b72beSEddie Cai 222*bf2b72beSEddie Cai static struct usb_request *rockusb_start_ep(struct usb_ep *ep) 223*bf2b72beSEddie Cai { 224*bf2b72beSEddie Cai struct usb_request *req; 225*bf2b72beSEddie Cai 226*bf2b72beSEddie Cai req = usb_ep_alloc_request(ep, 0); 227*bf2b72beSEddie Cai if (!req) 228*bf2b72beSEddie Cai return NULL; 229*bf2b72beSEddie Cai 230*bf2b72beSEddie Cai req->length = EP_BUFFER_SIZE; 231*bf2b72beSEddie Cai req->buf = memalign(CONFIG_SYS_CACHELINE_SIZE, EP_BUFFER_SIZE); 232*bf2b72beSEddie Cai if (!req->buf) { 233*bf2b72beSEddie Cai usb_ep_free_request(ep, req); 234*bf2b72beSEddie Cai return NULL; 235*bf2b72beSEddie Cai } 236*bf2b72beSEddie Cai memset(req->buf, 0, req->length); 237*bf2b72beSEddie Cai 238*bf2b72beSEddie Cai return req; 239*bf2b72beSEddie Cai } 240*bf2b72beSEddie Cai 241*bf2b72beSEddie Cai static int rockusb_set_alt(struct usb_function *f, unsigned int interface, 242*bf2b72beSEddie Cai unsigned int alt) 243*bf2b72beSEddie Cai { 244*bf2b72beSEddie Cai int ret; 245*bf2b72beSEddie Cai struct usb_composite_dev *cdev = f->config->cdev; 246*bf2b72beSEddie Cai struct usb_gadget *gadget = cdev->gadget; 247*bf2b72beSEddie Cai struct f_rockusb *f_rkusb = func_to_rockusb(f); 248*bf2b72beSEddie Cai const struct usb_endpoint_descriptor *d; 249*bf2b72beSEddie Cai 250*bf2b72beSEddie Cai debug("%s: func: %s intf: %d alt: %d\n", 251*bf2b72beSEddie Cai __func__, f->name, interface, alt); 252*bf2b72beSEddie Cai 253*bf2b72beSEddie Cai d = rkusb_ep_desc(gadget, &fs_ep_out, &hs_ep_out); 254*bf2b72beSEddie Cai ret = usb_ep_enable(f_rkusb->out_ep, d); 255*bf2b72beSEddie Cai if (ret) { 256*bf2b72beSEddie Cai printf("failed to enable out ep\n"); 257*bf2b72beSEddie Cai return ret; 258*bf2b72beSEddie Cai } 259*bf2b72beSEddie Cai 260*bf2b72beSEddie Cai f_rkusb->out_req = rockusb_start_ep(f_rkusb->out_ep); 261*bf2b72beSEddie Cai if (!f_rkusb->out_req) { 262*bf2b72beSEddie Cai printf("failed to alloc out req\n"); 263*bf2b72beSEddie Cai ret = -EINVAL; 264*bf2b72beSEddie Cai goto err; 265*bf2b72beSEddie Cai } 266*bf2b72beSEddie Cai f_rkusb->out_req->complete = rx_handler_command; 267*bf2b72beSEddie Cai 268*bf2b72beSEddie Cai d = rkusb_ep_desc(gadget, &fs_ep_in, &hs_ep_in); 269*bf2b72beSEddie Cai ret = usb_ep_enable(f_rkusb->in_ep, d); 270*bf2b72beSEddie Cai if (ret) { 271*bf2b72beSEddie Cai printf("failed to enable in ep\n"); 272*bf2b72beSEddie Cai goto err; 273*bf2b72beSEddie Cai } 274*bf2b72beSEddie Cai 275*bf2b72beSEddie Cai f_rkusb->in_req = rockusb_start_ep(f_rkusb->in_ep); 276*bf2b72beSEddie Cai if (!f_rkusb->in_req) { 277*bf2b72beSEddie Cai printf("failed alloc req in\n"); 278*bf2b72beSEddie Cai ret = -EINVAL; 279*bf2b72beSEddie Cai goto err; 280*bf2b72beSEddie Cai } 281*bf2b72beSEddie Cai f_rkusb->in_req->complete = rockusb_complete; 282*bf2b72beSEddie Cai 283*bf2b72beSEddie Cai ret = usb_ep_queue(f_rkusb->out_ep, f_rkusb->out_req, 0); 284*bf2b72beSEddie Cai if (ret) 285*bf2b72beSEddie Cai goto err; 286*bf2b72beSEddie Cai 287*bf2b72beSEddie Cai return 0; 288*bf2b72beSEddie Cai err: 289*bf2b72beSEddie Cai rockusb_disable(f); 290*bf2b72beSEddie Cai return ret; 291*bf2b72beSEddie Cai } 292*bf2b72beSEddie Cai 293*bf2b72beSEddie Cai static int rockusb_add(struct usb_configuration *c) 294*bf2b72beSEddie Cai { 295*bf2b72beSEddie Cai struct f_rockusb *f_rkusb = get_rkusb(); 296*bf2b72beSEddie Cai int status; 297*bf2b72beSEddie Cai 298*bf2b72beSEddie Cai debug("%s: cdev: 0x%p\n", __func__, c->cdev); 299*bf2b72beSEddie Cai 300*bf2b72beSEddie Cai f_rkusb->usb_function.name = "f_rockusb"; 301*bf2b72beSEddie Cai f_rkusb->usb_function.bind = rockusb_bind; 302*bf2b72beSEddie Cai f_rkusb->usb_function.unbind = rockusb_unbind; 303*bf2b72beSEddie Cai f_rkusb->usb_function.set_alt = rockusb_set_alt; 304*bf2b72beSEddie Cai f_rkusb->usb_function.disable = rockusb_disable; 305*bf2b72beSEddie Cai f_rkusb->usb_function.strings = rkusb_strings; 306*bf2b72beSEddie Cai 307*bf2b72beSEddie Cai status = usb_add_function(c, &f_rkusb->usb_function); 308*bf2b72beSEddie Cai if (status) { 309*bf2b72beSEddie Cai free(f_rkusb); 310*bf2b72beSEddie Cai rockusb_func = f_rkusb; 311*bf2b72beSEddie Cai } 312*bf2b72beSEddie Cai return status; 313*bf2b72beSEddie Cai } 314*bf2b72beSEddie Cai 315*bf2b72beSEddie Cai void rockusb_dev_init(char *dev_type, int dev_index) 316*bf2b72beSEddie Cai { 317*bf2b72beSEddie Cai struct f_rockusb *f_rkusb = get_rkusb(); 318*bf2b72beSEddie Cai 319*bf2b72beSEddie Cai f_rkusb->dev_type = dev_type; 320*bf2b72beSEddie Cai f_rkusb->dev_index = dev_index; 321*bf2b72beSEddie Cai } 322*bf2b72beSEddie Cai 323*bf2b72beSEddie Cai DECLARE_GADGET_BIND_CALLBACK(usb_dnl_rockusb, rockusb_add); 324*bf2b72beSEddie Cai 325*bf2b72beSEddie Cai static int rockusb_tx_write(const char *buffer, unsigned int buffer_size) 326*bf2b72beSEddie Cai { 327*bf2b72beSEddie Cai struct usb_request *in_req = rockusb_func->in_req; 328*bf2b72beSEddie Cai int ret; 329*bf2b72beSEddie Cai 330*bf2b72beSEddie Cai memcpy(in_req->buf, buffer, buffer_size); 331*bf2b72beSEddie Cai in_req->length = buffer_size; 332*bf2b72beSEddie Cai usb_ep_dequeue(rockusb_func->in_ep, in_req); 333*bf2b72beSEddie Cai ret = usb_ep_queue(rockusb_func->in_ep, in_req, 0); 334*bf2b72beSEddie Cai if (ret) 335*bf2b72beSEddie Cai printf("Error %d on queue\n", ret); 336*bf2b72beSEddie Cai return 0; 337*bf2b72beSEddie Cai } 338*bf2b72beSEddie Cai 339*bf2b72beSEddie Cai static int rockusb_tx_write_str(const char *buffer) 340*bf2b72beSEddie Cai { 341*bf2b72beSEddie Cai return rockusb_tx_write(buffer, strlen(buffer)); 342*bf2b72beSEddie Cai } 343*bf2b72beSEddie Cai 344*bf2b72beSEddie Cai #ifdef DEBUG 345*bf2b72beSEddie Cai static void printcbw(char *buf) 346*bf2b72beSEddie Cai { 347*bf2b72beSEddie Cai ALLOC_CACHE_ALIGN_BUFFER(struct fsg_bulk_cb_wrap, cbw, 348*bf2b72beSEddie Cai sizeof(struct fsg_bulk_cb_wrap)); 349*bf2b72beSEddie Cai 350*bf2b72beSEddie Cai memcpy((char *)cbw, buf, USB_BULK_CB_WRAP_LEN); 351*bf2b72beSEddie Cai 352*bf2b72beSEddie Cai debug("cbw: signature:%x\n", cbw->signature); 353*bf2b72beSEddie Cai debug("cbw: tag=%x\n", cbw->tag); 354*bf2b72beSEddie Cai debug("cbw: data_transfer_length=%d\n", cbw->data_transfer_length); 355*bf2b72beSEddie Cai debug("cbw: flags=%x\n", cbw->flags); 356*bf2b72beSEddie Cai debug("cbw: lun=%d\n", cbw->lun); 357*bf2b72beSEddie Cai debug("cbw: length=%d\n", cbw->length); 358*bf2b72beSEddie Cai debug("cbw: ucOperCode=%x\n", cbw->CDB[0]); 359*bf2b72beSEddie Cai debug("cbw: ucReserved=%x\n", cbw->CDB[1]); 360*bf2b72beSEddie Cai debug("cbw: dwAddress:%x %x %x %x\n", cbw->CDB[5], cbw->CDB[4], 361*bf2b72beSEddie Cai cbw->CDB[3], cbw->CDB[2]); 362*bf2b72beSEddie Cai debug("cbw: ucReserved2=%x\n", cbw->CDB[6]); 363*bf2b72beSEddie Cai debug("cbw: uslength:%x %x\n", cbw->CDB[8], cbw->CDB[7]); 364*bf2b72beSEddie Cai } 365*bf2b72beSEddie Cai 366*bf2b72beSEddie Cai static void printcsw(char *buf) 367*bf2b72beSEddie Cai { 368*bf2b72beSEddie Cai ALLOC_CACHE_ALIGN_BUFFER(struct bulk_cs_wrap, csw, 369*bf2b72beSEddie Cai sizeof(struct bulk_cs_wrap)); 370*bf2b72beSEddie Cai memcpy((char *)csw, buf, USB_BULK_CS_WRAP_LEN); 371*bf2b72beSEddie Cai debug("csw: signature:%x\n", csw->signature); 372*bf2b72beSEddie Cai debug("csw: tag:%x\n", csw->tag); 373*bf2b72beSEddie Cai debug("csw: residue:%x\n", csw->residue); 374*bf2b72beSEddie Cai debug("csw: status:%x\n", csw->status); 375*bf2b72beSEddie Cai } 376*bf2b72beSEddie Cai #endif 377*bf2b72beSEddie Cai 378*bf2b72beSEddie Cai static int rockusb_tx_write_csw(u32 tag, int residue, u8 status, int size) 379*bf2b72beSEddie Cai { 380*bf2b72beSEddie Cai ALLOC_CACHE_ALIGN_BUFFER(struct bulk_cs_wrap, csw, 381*bf2b72beSEddie Cai sizeof(struct bulk_cs_wrap)); 382*bf2b72beSEddie Cai csw->signature = cpu_to_le32(USB_BULK_CS_SIG); 383*bf2b72beSEddie Cai csw->tag = tag; 384*bf2b72beSEddie Cai csw->residue = cpu_to_be32(residue); 385*bf2b72beSEddie Cai csw->status = status; 386*bf2b72beSEddie Cai #ifdef DEBUG 387*bf2b72beSEddie Cai printcsw((char *)&csw); 388*bf2b72beSEddie Cai #endif 389*bf2b72beSEddie Cai return rockusb_tx_write((char *)csw, size); 390*bf2b72beSEddie Cai } 391*bf2b72beSEddie Cai 392*bf2b72beSEddie Cai static unsigned int rx_bytes_expected(struct usb_ep *ep) 393*bf2b72beSEddie Cai { 394*bf2b72beSEddie Cai struct f_rockusb *f_rkusb = get_rkusb(); 395*bf2b72beSEddie Cai int rx_remain = f_rkusb->dl_size - f_rkusb->dl_bytes; 396*bf2b72beSEddie Cai unsigned int rem; 397*bf2b72beSEddie Cai unsigned int maxpacket = ep->maxpacket; 398*bf2b72beSEddie Cai 399*bf2b72beSEddie Cai if (rx_remain <= 0) 400*bf2b72beSEddie Cai return 0; 401*bf2b72beSEddie Cai else if (rx_remain > EP_BUFFER_SIZE) 402*bf2b72beSEddie Cai return EP_BUFFER_SIZE; 403*bf2b72beSEddie Cai 404*bf2b72beSEddie Cai rem = rx_remain % maxpacket; 405*bf2b72beSEddie Cai if (rem > 0) 406*bf2b72beSEddie Cai rx_remain = rx_remain + (maxpacket - rem); 407*bf2b72beSEddie Cai 408*bf2b72beSEddie Cai return rx_remain; 409*bf2b72beSEddie Cai } 410*bf2b72beSEddie Cai 411*bf2b72beSEddie Cai /* usb_request complete call back to handle down load image */ 412*bf2b72beSEddie Cai static void rx_handler_dl_image(struct usb_ep *ep, struct usb_request *req) 413*bf2b72beSEddie Cai { 414*bf2b72beSEddie Cai struct f_rockusb *f_rkusb = get_rkusb(); 415*bf2b72beSEddie Cai unsigned int transfer_size = 0; 416*bf2b72beSEddie Cai const unsigned char *buffer = req->buf; 417*bf2b72beSEddie Cai unsigned int buffer_size = req->actual; 418*bf2b72beSEddie Cai 419*bf2b72beSEddie Cai transfer_size = f_rkusb->dl_size - f_rkusb->dl_bytes; 420*bf2b72beSEddie Cai if (!f_rkusb->desc) { 421*bf2b72beSEddie Cai char *type = f_rkusb->dev_type; 422*bf2b72beSEddie Cai int index = f_rkusb->dev_index; 423*bf2b72beSEddie Cai 424*bf2b72beSEddie Cai f_rkusb->desc = blk_get_dev(type, index); 425*bf2b72beSEddie Cai if (!f_rkusb->desc || 426*bf2b72beSEddie Cai f_rkusb->desc->type == DEV_TYPE_UNKNOWN) { 427*bf2b72beSEddie Cai puts("invalid mmc device\n"); 428*bf2b72beSEddie Cai rockusb_tx_write_csw(f_rkusb->tag, 0, CSW_FAIL, 429*bf2b72beSEddie Cai USB_BULK_CS_WRAP_LEN); 430*bf2b72beSEddie Cai return; 431*bf2b72beSEddie Cai } 432*bf2b72beSEddie Cai } 433*bf2b72beSEddie Cai 434*bf2b72beSEddie Cai if (req->status != 0) { 435*bf2b72beSEddie Cai printf("Bad status: %d\n", req->status); 436*bf2b72beSEddie Cai rockusb_tx_write_csw(f_rkusb->tag, 0, CSW_FAIL, 437*bf2b72beSEddie Cai USB_BULK_CS_WRAP_LEN); 438*bf2b72beSEddie Cai return; 439*bf2b72beSEddie Cai } 440*bf2b72beSEddie Cai 441*bf2b72beSEddie Cai if (buffer_size < transfer_size) 442*bf2b72beSEddie Cai transfer_size = buffer_size; 443*bf2b72beSEddie Cai 444*bf2b72beSEddie Cai memcpy((void *)f_rkusb->buf, buffer, transfer_size); 445*bf2b72beSEddie Cai f_rkusb->dl_bytes += transfer_size; 446*bf2b72beSEddie Cai int blks = 0, blkcnt = transfer_size / 512; 447*bf2b72beSEddie Cai 448*bf2b72beSEddie Cai debug("dl %x bytes, %x blks, write lba %x, dl_size:%x, dl_bytes:%x, ", 449*bf2b72beSEddie Cai transfer_size, blkcnt, f_rkusb->lba, f_rkusb->dl_size, 450*bf2b72beSEddie Cai f_rkusb->dl_bytes); 451*bf2b72beSEddie Cai blks = blk_dwrite(f_rkusb->desc, f_rkusb->lba, blkcnt, f_rkusb->buf); 452*bf2b72beSEddie Cai if (blks != blkcnt) { 453*bf2b72beSEddie Cai printf("failed writing to device %s: %d\n", f_rkusb->dev_type, 454*bf2b72beSEddie Cai f_rkusb->dev_index); 455*bf2b72beSEddie Cai rockusb_tx_write_csw(f_rkusb->tag, 0, CSW_FAIL, 456*bf2b72beSEddie Cai USB_BULK_CS_WRAP_LEN); 457*bf2b72beSEddie Cai return; 458*bf2b72beSEddie Cai } 459*bf2b72beSEddie Cai f_rkusb->lba += blkcnt; 460*bf2b72beSEddie Cai 461*bf2b72beSEddie Cai /* Check if transfer is done */ 462*bf2b72beSEddie Cai if (f_rkusb->dl_bytes >= f_rkusb->dl_size) { 463*bf2b72beSEddie Cai req->complete = rx_handler_command; 464*bf2b72beSEddie Cai req->length = EP_BUFFER_SIZE; 465*bf2b72beSEddie Cai f_rkusb->buf = f_rkusb->buf_head; 466*bf2b72beSEddie Cai printf("transfer 0x%x bytes done\n", f_rkusb->dl_size); 467*bf2b72beSEddie Cai f_rkusb->dl_size = 0; 468*bf2b72beSEddie Cai rockusb_tx_write_csw(f_rkusb->tag, 0, CSW_GOOD, 469*bf2b72beSEddie Cai USB_BULK_CS_WRAP_LEN); 470*bf2b72beSEddie Cai } else { 471*bf2b72beSEddie Cai req->length = rx_bytes_expected(ep); 472*bf2b72beSEddie Cai if (f_rkusb->buf == f_rkusb->buf_head) 473*bf2b72beSEddie Cai f_rkusb->buf = f_rkusb->buf_head + EP_BUFFER_SIZE; 474*bf2b72beSEddie Cai else 475*bf2b72beSEddie Cai f_rkusb->buf = f_rkusb->buf_head; 476*bf2b72beSEddie Cai 477*bf2b72beSEddie Cai debug("remain %x bytes, %x sectors\n", req->length, 478*bf2b72beSEddie Cai req->length / 512); 479*bf2b72beSEddie Cai } 480*bf2b72beSEddie Cai 481*bf2b72beSEddie Cai req->actual = 0; 482*bf2b72beSEddie Cai usb_ep_queue(ep, req, 0); 483*bf2b72beSEddie Cai } 484*bf2b72beSEddie Cai 485*bf2b72beSEddie Cai static void cb_test_unit_ready(struct usb_ep *ep, struct usb_request *req) 486*bf2b72beSEddie Cai { 487*bf2b72beSEddie Cai ALLOC_CACHE_ALIGN_BUFFER(struct fsg_bulk_cb_wrap, cbw, 488*bf2b72beSEddie Cai sizeof(struct fsg_bulk_cb_wrap)); 489*bf2b72beSEddie Cai 490*bf2b72beSEddie Cai memcpy((char *)cbw, req->buf, USB_BULK_CB_WRAP_LEN); 491*bf2b72beSEddie Cai 492*bf2b72beSEddie Cai rockusb_tx_write_csw(cbw->tag, cbw->data_transfer_length, 493*bf2b72beSEddie Cai CSW_GOOD, USB_BULK_CS_WRAP_LEN); 494*bf2b72beSEddie Cai } 495*bf2b72beSEddie Cai 496*bf2b72beSEddie Cai static void cb_read_storage_id(struct usb_ep *ep, struct usb_request *req) 497*bf2b72beSEddie Cai { 498*bf2b72beSEddie Cai ALLOC_CACHE_ALIGN_BUFFER(struct fsg_bulk_cb_wrap, cbw, 499*bf2b72beSEddie Cai sizeof(struct fsg_bulk_cb_wrap)); 500*bf2b72beSEddie Cai char emmc_id[] = "EMMC "; 501*bf2b72beSEddie Cai 502*bf2b72beSEddie Cai printf("read storage id\n"); 503*bf2b72beSEddie Cai memcpy((char *)cbw, req->buf, USB_BULK_CB_WRAP_LEN); 504*bf2b72beSEddie Cai rockusb_tx_write_str(emmc_id); 505*bf2b72beSEddie Cai rockusb_tx_write_csw(cbw->tag, cbw->data_transfer_length, CSW_GOOD, 506*bf2b72beSEddie Cai USB_BULK_CS_WRAP_LEN); 507*bf2b72beSEddie Cai } 508*bf2b72beSEddie Cai 509*bf2b72beSEddie Cai static void cb_write_lba(struct usb_ep *ep, struct usb_request *req) 510*bf2b72beSEddie Cai { 511*bf2b72beSEddie Cai ALLOC_CACHE_ALIGN_BUFFER(struct fsg_bulk_cb_wrap, cbw, 512*bf2b72beSEddie Cai sizeof(struct fsg_bulk_cb_wrap)); 513*bf2b72beSEddie Cai struct f_rockusb *f_rkusb = get_rkusb(); 514*bf2b72beSEddie Cai int sector_count; 515*bf2b72beSEddie Cai 516*bf2b72beSEddie Cai memcpy((char *)cbw, req->buf, USB_BULK_CB_WRAP_LEN); 517*bf2b72beSEddie Cai sector_count = (int)get_unaligned_be16(&cbw->CDB[7]); 518*bf2b72beSEddie Cai f_rkusb->lba = get_unaligned_be32(&cbw->CDB[2]); 519*bf2b72beSEddie Cai f_rkusb->dl_size = sector_count * 512; 520*bf2b72beSEddie Cai f_rkusb->dl_bytes = 0; 521*bf2b72beSEddie Cai f_rkusb->tag = cbw->tag; 522*bf2b72beSEddie Cai debug("require write %x bytes, %x sectors to lba %x\n", 523*bf2b72beSEddie Cai f_rkusb->dl_size, sector_count, f_rkusb->lba); 524*bf2b72beSEddie Cai 525*bf2b72beSEddie Cai if (f_rkusb->dl_size == 0) { 526*bf2b72beSEddie Cai rockusb_tx_write_csw(cbw->tag, cbw->data_transfer_length, 527*bf2b72beSEddie Cai CSW_FAIL, USB_BULK_CS_WRAP_LEN); 528*bf2b72beSEddie Cai } else { 529*bf2b72beSEddie Cai req->complete = rx_handler_dl_image; 530*bf2b72beSEddie Cai req->length = rx_bytes_expected(ep); 531*bf2b72beSEddie Cai } 532*bf2b72beSEddie Cai } 533*bf2b72beSEddie Cai 534*bf2b72beSEddie Cai void __weak rkusb_set_reboot_flag(int flag) 535*bf2b72beSEddie Cai { 536*bf2b72beSEddie Cai struct f_rockusb *f_rkusb = get_rkusb(); 537*bf2b72beSEddie Cai 538*bf2b72beSEddie Cai printf("rockkusb set reboot flag: %d\n", f_rkusb->reboot_flag); 539*bf2b72beSEddie Cai } 540*bf2b72beSEddie Cai 541*bf2b72beSEddie Cai static void compl_do_reset(struct usb_ep *ep, struct usb_request *req) 542*bf2b72beSEddie Cai { 543*bf2b72beSEddie Cai struct f_rockusb *f_rkusb = get_rkusb(); 544*bf2b72beSEddie Cai 545*bf2b72beSEddie Cai rkusb_set_reboot_flag(f_rkusb->reboot_flag); 546*bf2b72beSEddie Cai do_reset(NULL, 0, 0, NULL); 547*bf2b72beSEddie Cai } 548*bf2b72beSEddie Cai 549*bf2b72beSEddie Cai static void cb_reboot(struct usb_ep *ep, struct usb_request *req) 550*bf2b72beSEddie Cai { 551*bf2b72beSEddie Cai ALLOC_CACHE_ALIGN_BUFFER(struct fsg_bulk_cb_wrap, cbw, 552*bf2b72beSEddie Cai sizeof(struct fsg_bulk_cb_wrap)); 553*bf2b72beSEddie Cai struct f_rockusb *f_rkusb = get_rkusb(); 554*bf2b72beSEddie Cai 555*bf2b72beSEddie Cai f_rkusb->reboot_flag = 0; 556*bf2b72beSEddie Cai memcpy((char *)cbw, req->buf, USB_BULK_CB_WRAP_LEN); 557*bf2b72beSEddie Cai f_rkusb->reboot_flag = cbw->CDB[1]; 558*bf2b72beSEddie Cai rockusb_func->in_req->complete = compl_do_reset; 559*bf2b72beSEddie Cai rockusb_tx_write_csw(cbw->tag, cbw->data_transfer_length, CSW_GOOD, 560*bf2b72beSEddie Cai USB_BULK_CS_WRAP_LEN); 561*bf2b72beSEddie Cai } 562*bf2b72beSEddie Cai 563*bf2b72beSEddie Cai static void cb_not_support(struct usb_ep *ep, struct usb_request *req) 564*bf2b72beSEddie Cai { 565*bf2b72beSEddie Cai ALLOC_CACHE_ALIGN_BUFFER(struct fsg_bulk_cb_wrap, cbw, 566*bf2b72beSEddie Cai sizeof(struct fsg_bulk_cb_wrap)); 567*bf2b72beSEddie Cai 568*bf2b72beSEddie Cai memcpy((char *)cbw, req->buf, USB_BULK_CB_WRAP_LEN); 569*bf2b72beSEddie Cai printf("Rockusb command %x not support yet\n", cbw->CDB[0]); 570*bf2b72beSEddie Cai rockusb_tx_write_csw(cbw->tag, 0, CSW_FAIL, USB_BULK_CS_WRAP_LEN); 571*bf2b72beSEddie Cai } 572*bf2b72beSEddie Cai 573*bf2b72beSEddie Cai static const struct cmd_dispatch_info cmd_dispatch_info[] = { 574*bf2b72beSEddie Cai { 575*bf2b72beSEddie Cai .cmd = K_FW_TEST_UNIT_READY, 576*bf2b72beSEddie Cai .cb = cb_test_unit_ready, 577*bf2b72beSEddie Cai }, 578*bf2b72beSEddie Cai { 579*bf2b72beSEddie Cai .cmd = K_FW_READ_FLASH_ID, 580*bf2b72beSEddie Cai .cb = cb_read_storage_id, 581*bf2b72beSEddie Cai }, 582*bf2b72beSEddie Cai { 583*bf2b72beSEddie Cai .cmd = K_FW_SET_DEVICE_ID, 584*bf2b72beSEddie Cai .cb = cb_not_support, 585*bf2b72beSEddie Cai }, 586*bf2b72beSEddie Cai { 587*bf2b72beSEddie Cai .cmd = K_FW_TEST_BAD_BLOCK, 588*bf2b72beSEddie Cai .cb = cb_not_support, 589*bf2b72beSEddie Cai }, 590*bf2b72beSEddie Cai { 591*bf2b72beSEddie Cai .cmd = K_FW_READ_10, 592*bf2b72beSEddie Cai .cb = cb_not_support, 593*bf2b72beSEddie Cai }, 594*bf2b72beSEddie Cai { 595*bf2b72beSEddie Cai .cmd = K_FW_WRITE_10, 596*bf2b72beSEddie Cai .cb = cb_not_support, 597*bf2b72beSEddie Cai }, 598*bf2b72beSEddie Cai { 599*bf2b72beSEddie Cai .cmd = K_FW_ERASE_10, 600*bf2b72beSEddie Cai .cb = cb_not_support, 601*bf2b72beSEddie Cai }, 602*bf2b72beSEddie Cai { 603*bf2b72beSEddie Cai .cmd = K_FW_WRITE_SPARE, 604*bf2b72beSEddie Cai .cb = cb_not_support, 605*bf2b72beSEddie Cai }, 606*bf2b72beSEddie Cai { 607*bf2b72beSEddie Cai .cmd = K_FW_READ_SPARE, 608*bf2b72beSEddie Cai .cb = cb_not_support, 609*bf2b72beSEddie Cai }, 610*bf2b72beSEddie Cai { 611*bf2b72beSEddie Cai .cmd = K_FW_ERASE_10_FORCE, 612*bf2b72beSEddie Cai .cb = cb_not_support, 613*bf2b72beSEddie Cai }, 614*bf2b72beSEddie Cai { 615*bf2b72beSEddie Cai .cmd = K_FW_GET_VERSION, 616*bf2b72beSEddie Cai .cb = cb_not_support, 617*bf2b72beSEddie Cai }, 618*bf2b72beSEddie Cai { 619*bf2b72beSEddie Cai .cmd = K_FW_LBA_READ_10, 620*bf2b72beSEddie Cai .cb = cb_not_support, 621*bf2b72beSEddie Cai }, 622*bf2b72beSEddie Cai { 623*bf2b72beSEddie Cai .cmd = K_FW_LBA_WRITE_10, 624*bf2b72beSEddie Cai .cb = cb_write_lba, 625*bf2b72beSEddie Cai }, 626*bf2b72beSEddie Cai { 627*bf2b72beSEddie Cai .cmd = K_FW_ERASE_SYS_DISK, 628*bf2b72beSEddie Cai .cb = cb_not_support, 629*bf2b72beSEddie Cai }, 630*bf2b72beSEddie Cai { 631*bf2b72beSEddie Cai .cmd = K_FW_SDRAM_READ_10, 632*bf2b72beSEddie Cai .cb = cb_not_support, 633*bf2b72beSEddie Cai }, 634*bf2b72beSEddie Cai { 635*bf2b72beSEddie Cai .cmd = K_FW_SDRAM_WRITE_10, 636*bf2b72beSEddie Cai .cb = cb_not_support, 637*bf2b72beSEddie Cai }, 638*bf2b72beSEddie Cai { 639*bf2b72beSEddie Cai .cmd = K_FW_SDRAM_EXECUTE, 640*bf2b72beSEddie Cai .cb = cb_not_support, 641*bf2b72beSEddie Cai }, 642*bf2b72beSEddie Cai { 643*bf2b72beSEddie Cai .cmd = K_FW_READ_FLASH_INFO, 644*bf2b72beSEddie Cai .cb = cb_not_support, 645*bf2b72beSEddie Cai }, 646*bf2b72beSEddie Cai { 647*bf2b72beSEddie Cai .cmd = K_FW_GET_CHIP_VER, 648*bf2b72beSEddie Cai .cb = cb_not_support, 649*bf2b72beSEddie Cai }, 650*bf2b72beSEddie Cai { 651*bf2b72beSEddie Cai .cmd = K_FW_LOW_FORMAT, 652*bf2b72beSEddie Cai .cb = cb_not_support, 653*bf2b72beSEddie Cai }, 654*bf2b72beSEddie Cai { 655*bf2b72beSEddie Cai .cmd = K_FW_SET_RESET_FLAG, 656*bf2b72beSEddie Cai .cb = cb_not_support, 657*bf2b72beSEddie Cai }, 658*bf2b72beSEddie Cai { 659*bf2b72beSEddie Cai .cmd = K_FW_SPI_READ_10, 660*bf2b72beSEddie Cai .cb = cb_not_support, 661*bf2b72beSEddie Cai }, 662*bf2b72beSEddie Cai { 663*bf2b72beSEddie Cai .cmd = K_FW_SPI_WRITE_10, 664*bf2b72beSEddie Cai .cb = cb_not_support, 665*bf2b72beSEddie Cai }, 666*bf2b72beSEddie Cai { 667*bf2b72beSEddie Cai .cmd = K_FW_SESSION, 668*bf2b72beSEddie Cai .cb = cb_not_support, 669*bf2b72beSEddie Cai }, 670*bf2b72beSEddie Cai { 671*bf2b72beSEddie Cai .cmd = K_FW_RESET, 672*bf2b72beSEddie Cai .cb = cb_reboot, 673*bf2b72beSEddie Cai }, 674*bf2b72beSEddie Cai }; 675*bf2b72beSEddie Cai 676*bf2b72beSEddie Cai static void rx_handler_command(struct usb_ep *ep, struct usb_request *req) 677*bf2b72beSEddie Cai { 678*bf2b72beSEddie Cai void (*func_cb)(struct usb_ep *ep, struct usb_request *req) = NULL; 679*bf2b72beSEddie Cai 680*bf2b72beSEddie Cai ALLOC_CACHE_ALIGN_BUFFER(struct fsg_bulk_cb_wrap, cbw, 681*bf2b72beSEddie Cai sizeof(struct fsg_bulk_cb_wrap)); 682*bf2b72beSEddie Cai char *cmdbuf = req->buf; 683*bf2b72beSEddie Cai int i; 684*bf2b72beSEddie Cai 685*bf2b72beSEddie Cai if (req->status || req->length == 0) 686*bf2b72beSEddie Cai return; 687*bf2b72beSEddie Cai 688*bf2b72beSEddie Cai memcpy((char *)cbw, req->buf, USB_BULK_CB_WRAP_LEN); 689*bf2b72beSEddie Cai #ifdef DEBUG 690*bf2b72beSEddie Cai printcbw(req->buf); 691*bf2b72beSEddie Cai #endif 692*bf2b72beSEddie Cai 693*bf2b72beSEddie Cai for (i = 0; i < ARRAY_SIZE(cmd_dispatch_info); i++) { 694*bf2b72beSEddie Cai if (cmd_dispatch_info[i].cmd == cbw->CDB[0]) { 695*bf2b72beSEddie Cai func_cb = cmd_dispatch_info[i].cb; 696*bf2b72beSEddie Cai break; 697*bf2b72beSEddie Cai } 698*bf2b72beSEddie Cai } 699*bf2b72beSEddie Cai 700*bf2b72beSEddie Cai if (!func_cb) { 701*bf2b72beSEddie Cai printf("unknown command: %s\n", (char *)req->buf); 702*bf2b72beSEddie Cai rockusb_tx_write_str("FAILunknown command"); 703*bf2b72beSEddie Cai } else { 704*bf2b72beSEddie Cai if (req->actual < req->length) { 705*bf2b72beSEddie Cai u8 *buf = (u8 *)req->buf; 706*bf2b72beSEddie Cai 707*bf2b72beSEddie Cai buf[req->actual] = 0; 708*bf2b72beSEddie Cai func_cb(ep, req); 709*bf2b72beSEddie Cai } else { 710*bf2b72beSEddie Cai puts("buffer overflow\n"); 711*bf2b72beSEddie Cai rockusb_tx_write_str("FAILbuffer overflow"); 712*bf2b72beSEddie Cai } 713*bf2b72beSEddie Cai } 714*bf2b72beSEddie Cai 715*bf2b72beSEddie Cai *cmdbuf = '\0'; 716*bf2b72beSEddie Cai req->actual = 0; 717*bf2b72beSEddie Cai usb_ep_queue(ep, req, 0); 718*bf2b72beSEddie Cai } 719