[U-Boot] [PATCH 06/10] usb:g_dnl:f_thor: USB download function to support TIZEN's THOR protocol
Marek Vasut
marex at denx.de
Thu Oct 3 17:48:02 CEST 2013
Dear Lukasz Majewski,
[...]
> +static struct f_thor *thor_func;
> +static inline struct f_thor *func_to_thor(struct usb_function *f)
> +{
> + return container_of(f, struct f_thor, usb_function);
> +}
> +
> +DEFINE_CACHE_ALIGN_BUFFER(char, thor_tx_data_buf, sizeof(struct rsp_box));
> +DEFINE_CACHE_ALIGN_BUFFER(char, thor_rx_data_buf, sizeof(struct rqt_box));
This should either be uint8_t or unsigned char. A buffer shall not be (signed)
char.
Also, I suspect you want to use DEFINE_CACHE_ALIGN_BUFFER here, no ?
> +/* ********************************************************** */
> +/* THOR protocol - transmission handling */
> +/* ********************************************************** */
> +DEFINE_CACHE_ALIGN_BUFFER(char, f_name, F_NAME_BUF_SIZE);
Ditto
> +static unsigned long long int thor_file_size;
> +static int alt_setting_num;
> +
> +static void send_rsp(const struct rsp_box *rsp)
> +{
> + /* should be copy on dma duffer */
> + memcpy(thor_tx_data_buf, rsp, sizeof(struct rsp_box));
> + thor_tx_data(thor_tx_data_buf, sizeof(struct rsp_box));
> +
> + debug("-RSP: %d, %d\n", rsp->rsp, rsp->rsp_data);
> +}
> +
> +static void send_data_rsp(s32 ack, s32 count)
> +{
> + ALLOC_CACHE_ALIGN_BUFFER(struct data_rsp_box, rsp,
> + sizeof(struct data_rsp_box));
> +
> + rsp->ack = ack;
> + rsp->count = count;
> +
> + /* should be copy on dma duffer */
This comment really makes no sense to me.
> + memcpy(thor_tx_data_buf, rsp, sizeof(struct data_rsp_box));
> + thor_tx_data(thor_tx_data_buf, sizeof(struct data_rsp_box));
> +
> + debug("-DATA RSP: %d, %d\n", ack, count);
> +}
> +
> +static int process_rqt_info(const struct rqt_box *rqt)
> +{
> + ALLOC_CACHE_ALIGN_BUFFER(struct rsp_box, rsp, sizeof(struct rsp_box));
> + memset(rsp, '\0', sizeof(struct rsp_box));
> +
> + rsp->rsp = rqt->rqt;
> + rsp->rsp_data = rqt->rqt_data;
> +
> + switch (rqt->rqt_data) {
> + case RQT_INFO_VER_PROTOCOL:
> + rsp->int_data[0] = VER_PROTOCOL_MAJOR;
> + rsp->int_data[1] = VER_PROTOCOL_MINOR;
> + break;
> + case RQT_INIT_VER_HW:
> + snprintf(rsp->str_data[0], sizeof(rsp->str_data[0]),
> + "%x", checkboard());
> + break;
> + case RQT_INIT_VER_BOOT:
> + sprintf(rsp->str_data[0], "%s", U_BOOT_VERSION);
> + break;
> + case RQT_INIT_VER_KERNEL:
> + sprintf(rsp->str_data[0], "%s", "k unknown");
> + break;
> + case RQT_INIT_VER_PLATFORM:
> + sprintf(rsp->str_data[0], "%s", "p unknown");
> + break;
> + case RQT_INIT_VER_CSC:
> + sprintf(rsp->str_data[0], "%s", "c unknown");
> + break;
> + default:
> + return -EINVAL;
> + }
> +
> + send_rsp(rsp);
> + return true;
> +}
> +
> +static int process_rqt_cmd(const struct rqt_box *rqt)
> +{
> + ALLOC_CACHE_ALIGN_BUFFER(struct rsp_box, rsp, sizeof(struct rsp_box));
> + memset(rsp, '\0', sizeof(struct rsp_box));
memset(rsp, 0, sizeof() ... this '\0' is unneeded, fix globally.
> +
> + rsp->rsp = rqt->rqt;
> + rsp->rsp_data = rqt->rqt_data;
> +
> + switch (rqt->rqt_data) {
> + case RQT_CMD_REBOOT:
> + debug("TARGET RESET\n");
> + send_rsp(rsp);
> + g_dnl_unregister();
> + dfu_free_entities();
> + run_command("reset", 0);
> + break;
> + case RQT_CMD_POWEROFF:
> + case RQT_CMD_EFSCLEAR:
> + send_rsp(rsp);
This case fallthrough is intentional here ?
> + default:
> + printf("Command not supported -> cmd: %d\n", rqt->rqt_data);
> + return -EINVAL;
> + }
> +
> + return true;
> +}
[...]
[...]
> +static struct usb_cdc_call_mgmt_descriptor thor_downloader_cdc_call = {
> + .bLength = sizeof(thor_downloader_cdc_call),
> + .bDescriptorType = 0x24, /* CS_INTERFACE */
> + .bDescriptorSubType = 0x01,
> + .bmCapabilities = 0x00,
> + .bDataInterface = 0x01,
> +};
> +
> +struct usb_cdc_acm_descriptor thor_downloader_cdc_abstract = {
Why is this and the rest not static ?
> + .bLength = sizeof(thor_downloader_cdc_abstract),
> + .bDescriptorType = 0x24, /* CS_INTERFACE */
> + .bDescriptorSubType = 0x02,
> + .bmCapabilities = 0x00,
> +};
> +
> +struct usb_cdc_union_desc thor_downloader_cdc_union = {
> + .bLength = sizeof(thor_downloader_cdc_union),
> + .bDescriptorType = 0x24, /* CS_INTERFACE */
> + .bDescriptorSubType = USB_CDC_UNION_TYPE,
> +};
> +
> +static struct usb_endpoint_descriptor fs_int_desc = {
> + .bLength = USB_DT_ENDPOINT_SIZE,
> + .bDescriptorType = USB_DT_ENDPOINT,
> +
> + .bEndpointAddress = 3 | USB_DIR_IN,
> + .bmAttributes = USB_ENDPOINT_XFER_INT,
> + .wMaxPacketSize = __constant_cpu_to_le16(16),
> +
> + .bInterval = 0x9,
> +};
[...]
> +/*------------------------------------------------------------------------
> -*/ +static struct usb_request *alloc_ep_req(struct usb_ep *ep, unsigned
> length) +{
> + struct usb_request *req;
> +
> + req = usb_ep_alloc_request(ep, 0);
> + if (req) {
if (!req)
return ...
... rest of the code ...
> + req->length = length;
> + req->buf = memalign(CONFIG_SYS_CACHELINE_SIZE, length);
> + if (!req->buf) {
> + usb_ep_free_request(ep, req);
> + req = NULL;
> + }
> + }
> + return req;
> +}
[...]
> +static void thor_rx_tx_complete(struct usb_ep *ep, struct usb_request
> *req) +{
> + struct thor_dev *dev = thor_func->dev;
> + int status = req->status;
> +
> + debug("%s: ep_ptr:%p, req_ptr:%p\n", __func__, ep, req);
> + switch (status) {
> + case 0: /* normal completion? */
> + if (ep == dev->out_ep)
> + dev->rxdata = 1;
> + else
> + dev->txdata = 1;
> +
> + break;
> +
> + /* this endpoint is normally active while we're configured */
> + case -ECONNABORTED: /* hardware forced ep reset */
> + case -ECONNRESET: /* request dequeued */
> + case -ESHUTDOWN: /* disconnect from host */
> + /* Exeptional situation - print error message */
> +
> + case -EOVERFLOW:
> + error("ERROR:%d", status);
> + default:
> + debug("%s complete --> %d, %d/%d\n", ep->name,
> + status, req->actual, req->length);
> + case -EREMOTEIO: /* short read */
> + break;
> + }
You might want to fix the order of these cases here.
> +}
> +
> +static struct usb_request *thor_start_ep(struct usb_ep *ep)
> +{
> + struct usb_request *req;
> +
> + req = alloc_ep_req(ep, ep->maxpacket);
> + debug("%s: ep:%p req:%p\n", __func__, ep, req);
> +
> + if (!req)
> + return NULL;
> +
> + memset(req->buf, 0, req->length);
> + req->complete = thor_rx_tx_complete;
> +
> + memset(req->buf, 0x55, req->length);
> +
> + return req;
> +}
[...]
> +int thor_init(void)
> +{
> + struct thor_dev *dev = thor_func->dev;
> +
> + /* Wait for a device enumeration and configuration settings */
> + debug("THOR enumeration/configuration setting....\n");
> + while (!dev->configuration_done)
> + usb_gadget_handle_interrupts();
> +
> + thor_set_dma(thor_rx_data_buf, strlen(recv_key));
> + /* detect the download request from Host PC */
> + if (thor_rx_data() < 0) {
> + printf("%s: Data not received!\n", __func__);
> + return -1;
> + }
> +
> + if (strncmp(thor_rx_data_buf, recv_key, strlen(recv_key)) == 0) {
Use min() of upper bound on the recv_key length and this strlen()
> + puts("Download request from the Host PC\n");
> + udelay(30 * 1000); /* 30 ms */
> +
> + strncpy(thor_tx_data_buf, tx_key, strlen(tx_key));
> + thor_tx_data(thor_tx_data_buf, strlen(tx_key));
> + } else {
> + puts("Wrong reply information\n");
> + return -1;
> + }
> +
> + return 0;
> +}
[...]
> +static int thor_eps_setup(struct usb_function *f)
> +{
> + struct usb_composite_dev *cdev = f->config->cdev;
> + struct usb_gadget *gadget = cdev->gadget;
> + struct thor_dev *dev = thor_func->dev;
> + struct usb_endpoint_descriptor *d;
> + struct usb_request *req;
> + struct usb_ep *ep;
> + int result;
> +
> + ep = dev->in_ep;
> + d = ep_desc(gadget, &hs_in_desc, &fs_in_desc);
> + debug("(d)bEndpointAddress: 0x%x\n", d->bEndpointAddress);
> +
> + result = usb_ep_enable(ep, d);
> +
> + if (result == 0) {
if (result)
goto exit;
... the rest ...
> + ep->driver_data = cdev; /* claim */
> + req = thor_start_ep(ep);
> + if (req != NULL) {
> + dev->in_req = req;
> + } else {
> + usb_ep_disable(ep);
> + result = -EIO;
> + }
> + } else {
> + goto exit;
> + }
> + ep = dev->out_ep;
> + d = ep_desc(gadget, &hs_out_desc, &fs_out_desc);
> + debug("(d)bEndpointAddress: 0x%x\n", d->bEndpointAddress);
> +
> + result = usb_ep_enable(ep, d);
> +
> + if (result == 0) {
DTTO
> + ep->driver_data = cdev; /* claim */
> + req = thor_start_ep(ep);
> + if (req != NULL) {
> + dev->out_req = req;
> + } else {
> + usb_ep_disable(ep);
> + result = -EIO;
> + }
> + } else {
> + goto exit;
> + }
> + /* ACM control EP */
> + ep = dev->int_ep;
> + ep->driver_data = cdev; /* claim */
> +
> + exit:
> + return result;
> +}
[...]
Best regards,
Marek Vasut
More information about the U-Boot
mailing list