]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - drivers/usb/gadget/f_thor.c
Merge branch 'master' of git://git.denx.de/u-boot-arm
[karo-tx-uboot.git] / drivers / usb / gadget / f_thor.c
1 /*
2  * f_thor.c -- USB TIZEN THOR Downloader gadget function
3  *
4  * Copyright (C) 2013 Samsung Electronics
5  * Lukasz Majewski <l.majewski@samsung.com>
6  *
7  * Based on code from:
8  * git://review.tizen.org/kernel/u-boot
9  *
10  * Developed by:
11  * Copyright (C) 2009 Samsung Electronics
12  * Minkyu Kang <mk7.kang@samsung.com>
13  * Sanghee Kim <sh0130.kim@samsung.com>
14  *
15  * SPDX-License-Identifier:     GPL-2.0+
16  */
17
18 #include <errno.h>
19 #include <common.h>
20 #include <malloc.h>
21 #include <version.h>
22 #include <linux/usb/ch9.h>
23 #include <linux/usb/gadget.h>
24 #include <linux/usb/composite.h>
25 #include <linux/usb/cdc.h>
26 #include <g_dnl.h>
27 #include <dfu.h>
28
29 #include "f_thor.h"
30
31 static void thor_tx_data(unsigned char *data, int len);
32 static void thor_set_dma(void *addr, int len);
33 static int thor_rx_data(void);
34
35 static struct f_thor *thor_func;
36 static inline struct f_thor *func_to_thor(struct usb_function *f)
37 {
38         return container_of(f, struct f_thor, usb_function);
39 }
40
41 DEFINE_CACHE_ALIGN_BUFFER(unsigned char, thor_tx_data_buf,
42                           sizeof(struct rsp_box));
43 DEFINE_CACHE_ALIGN_BUFFER(unsigned char, thor_rx_data_buf,
44                           sizeof(struct rqt_box));
45
46 /* ********************************************************** */
47 /*         THOR protocol - transmission handling              */
48 /* ********************************************************** */
49 DEFINE_CACHE_ALIGN_BUFFER(char, f_name, F_NAME_BUF_SIZE);
50 static unsigned long long int thor_file_size;
51 static int alt_setting_num;
52
53 static void send_rsp(const struct rsp_box *rsp)
54 {
55         memcpy(thor_tx_data_buf, rsp, sizeof(struct rsp_box));
56         thor_tx_data(thor_tx_data_buf, sizeof(struct rsp_box));
57
58         debug("-RSP: %d, %d\n", rsp->rsp, rsp->rsp_data);
59 }
60
61 static void send_data_rsp(s32 ack, s32 count)
62 {
63         ALLOC_CACHE_ALIGN_BUFFER(struct data_rsp_box, rsp,
64                                  sizeof(struct data_rsp_box));
65
66         rsp->ack = ack;
67         rsp->count = count;
68
69         memcpy(thor_tx_data_buf, rsp, sizeof(struct data_rsp_box));
70         thor_tx_data(thor_tx_data_buf, sizeof(struct data_rsp_box));
71
72         debug("-DATA RSP: %d, %d\n", ack, count);
73 }
74
75 static int process_rqt_info(const struct rqt_box *rqt)
76 {
77         ALLOC_CACHE_ALIGN_BUFFER(struct rsp_box, rsp, sizeof(struct rsp_box));
78         memset(rsp, 0, sizeof(struct rsp_box));
79
80         rsp->rsp = rqt->rqt;
81         rsp->rsp_data = rqt->rqt_data;
82
83         switch (rqt->rqt_data) {
84         case RQT_INFO_VER_PROTOCOL:
85                 rsp->int_data[0] = VER_PROTOCOL_MAJOR;
86                 rsp->int_data[1] = VER_PROTOCOL_MINOR;
87                 break;
88         case RQT_INIT_VER_HW:
89                 snprintf(rsp->str_data[0], sizeof(rsp->str_data[0]),
90                          "%x", checkboard());
91                 break;
92         case RQT_INIT_VER_BOOT:
93                 sprintf(rsp->str_data[0], "%s", U_BOOT_VERSION);
94                 break;
95         case RQT_INIT_VER_KERNEL:
96                 sprintf(rsp->str_data[0], "%s", "k unknown");
97                 break;
98         case RQT_INIT_VER_PLATFORM:
99                 sprintf(rsp->str_data[0], "%s", "p unknown");
100                 break;
101         case RQT_INIT_VER_CSC:
102                 sprintf(rsp->str_data[0], "%s", "c unknown");
103                 break;
104         default:
105                 return -EINVAL;
106         }
107
108         send_rsp(rsp);
109         return true;
110 }
111
112 static int process_rqt_cmd(const struct rqt_box *rqt)
113 {
114         ALLOC_CACHE_ALIGN_BUFFER(struct rsp_box, rsp, sizeof(struct rsp_box));
115         memset(rsp, 0, sizeof(struct rsp_box));
116
117         rsp->rsp = rqt->rqt;
118         rsp->rsp_data = rqt->rqt_data;
119
120         switch (rqt->rqt_data) {
121         case RQT_CMD_REBOOT:
122                 debug("TARGET RESET\n");
123                 send_rsp(rsp);
124                 g_dnl_unregister();
125                 dfu_free_entities();
126                 run_command("reset", 0);
127                 break;
128         case RQT_CMD_POWEROFF:
129         case RQT_CMD_EFSCLEAR:
130                 send_rsp(rsp);
131         default:
132                 printf("Command not supported -> cmd: %d\n", rqt->rqt_data);
133                 return -EINVAL;
134         }
135
136         return true;
137 }
138
139 static long long int download_head(unsigned long long total,
140                                    unsigned int packet_size,
141                                    long long int *left,
142                                    int *cnt)
143 {
144         long long int rcv_cnt = 0, left_to_rcv, ret_rcv;
145         void *transfer_buffer = dfu_get_buf();
146         void *buf = transfer_buffer;
147         int usb_pkt_cnt = 0, ret;
148
149         /*
150          * Files smaller than THOR_STORE_UNIT_SIZE (now 32 MiB) are stored on
151          * the medium.
152          * The packet response is sent on the purpose after successful data
153          * chunk write. There is a room for improvement when asynchronous write
154          * is performed.
155          */
156         while (total - rcv_cnt >= packet_size) {
157                 thor_set_dma(buf, packet_size);
158                 buf += packet_size;
159                 ret_rcv = thor_rx_data();
160                 if (ret_rcv < 0)
161                         return ret_rcv;
162                 rcv_cnt += ret_rcv;
163                 debug("%d: RCV data count: %llu cnt: %d\n", usb_pkt_cnt,
164                       rcv_cnt, *cnt);
165
166                 if ((rcv_cnt % THOR_STORE_UNIT_SIZE) == 0) {
167                         ret = dfu_write(dfu_get_entity(alt_setting_num),
168                                         transfer_buffer, THOR_STORE_UNIT_SIZE,
169                                         (*cnt)++);
170                         if (ret) {
171                                 error("DFU write failed [%d] cnt: %d",
172                                       ret, *cnt);
173                                 return ret;
174                         }
175                         buf = transfer_buffer;
176                 }
177                 send_data_rsp(0, ++usb_pkt_cnt);
178         }
179
180         /* Calculate the amount of data to arrive from PC (in bytes) */
181         left_to_rcv = total - rcv_cnt;
182
183         /*
184          * Calculate number of data already received. but not yet stored
185          * on the medium (they are smaller than THOR_STORE_UNIT_SIZE)
186          */
187         *left = left_to_rcv + buf - transfer_buffer;
188         debug("%s: left: %llu left_to_rcv: %llu buf: 0x%p\n", __func__,
189               *left, left_to_rcv, buf);
190
191         if (left_to_rcv) {
192                 thor_set_dma(buf, packet_size);
193                 ret_rcv = thor_rx_data();
194                 if (ret_rcv < 0)
195                         return ret_rcv;
196                 rcv_cnt += ret_rcv;
197                 send_data_rsp(0, ++usb_pkt_cnt);
198         }
199
200         debug("%s: %llu total: %llu cnt: %d\n", __func__, rcv_cnt, total, *cnt);
201
202         return rcv_cnt;
203 }
204
205 static int download_tail(long long int left, int cnt)
206 {
207         struct dfu_entity *dfu_entity = dfu_get_entity(alt_setting_num);
208         void *transfer_buffer = dfu_get_buf();
209         int ret;
210
211         debug("%s: left: %llu cnt: %d\n", __func__, left, cnt);
212
213         if (left) {
214                 ret = dfu_write(dfu_entity, transfer_buffer, left, cnt++);
215                 if (ret) {
216                         error("DFU write failed [%d]: left: %llu", ret, left);
217                         return ret;
218                 }
219         }
220
221         /*
222          * To store last "packet" DFU storage backend requires dfu_write with
223          * size parameter equal to 0
224          *
225          * This also frees memory malloc'ed by dfu_get_buf(), so no explicit
226          * need fo call dfu_free_buf() is needed.
227          */
228         ret = dfu_write(dfu_entity, transfer_buffer, 0, cnt);
229         if (ret)
230                 error("DFU write failed [%d] cnt: %d", ret, cnt);
231
232         ret = dfu_flush(dfu_entity, transfer_buffer, 0, cnt);
233         if (ret) {
234                 error("DFU flush failed!");
235                 return ret;
236         }
237
238         return ret;
239 }
240
241 static long long int process_rqt_download(const struct rqt_box *rqt)
242 {
243         ALLOC_CACHE_ALIGN_BUFFER(struct rsp_box, rsp, sizeof(struct rsp_box));
244         static long long int left, ret_head;
245         int file_type, ret = 0;
246         static int cnt;
247
248         memset(rsp, 0, sizeof(struct rsp_box));
249         rsp->rsp = rqt->rqt;
250         rsp->rsp_data = rqt->rqt_data;
251
252         switch (rqt->rqt_data) {
253         case RQT_DL_INIT:
254                 thor_file_size = rqt->int_data[0];
255                 debug("INIT: total %d bytes\n", rqt->int_data[0]);
256                 break;
257         case RQT_DL_FILE_INFO:
258                 file_type = rqt->int_data[0];
259                 if (file_type == FILE_TYPE_PIT) {
260                         puts("PIT table file - not supported\n");
261                         rsp->ack = -ENOTSUPP;
262                         ret = rsp->ack;
263                         break;
264                 }
265
266                 thor_file_size = rqt->int_data[1];
267                 memcpy(f_name, rqt->str_data[0], F_NAME_BUF_SIZE);
268
269                 debug("INFO: name(%s, %d), size(%llu), type(%d)\n",
270                       f_name, 0, thor_file_size, file_type);
271
272                 rsp->int_data[0] = THOR_PACKET_SIZE;
273
274                 alt_setting_num = dfu_get_alt(f_name);
275                 if (alt_setting_num < 0) {
276                         error("Alt setting [%d] to write not found!",
277                               alt_setting_num);
278                         rsp->ack = -ENODEV;
279                         ret = rsp->ack;
280                 }
281                 break;
282         case RQT_DL_FILE_START:
283                 send_rsp(rsp);
284                 ret_head = download_head(thor_file_size, THOR_PACKET_SIZE,
285                                          &left, &cnt);
286                 if (ret_head < 0) {
287                         left = 0;
288                         cnt = 0;
289                 }
290                 return ret_head;
291         case RQT_DL_FILE_END:
292                 debug("DL FILE_END\n");
293                 rsp->ack = download_tail(left, cnt);
294                 ret = rsp->ack;
295                 left = 0;
296                 cnt = 0;
297                 break;
298         case RQT_DL_EXIT:
299                 debug("DL EXIT\n");
300                 break;
301         default:
302                 error("Operation not supported: %d", rqt->rqt_data);
303                 ret = -ENOTSUPP;
304         }
305
306         send_rsp(rsp);
307         return ret;
308 }
309
310 static int process_data(void)
311 {
312         ALLOC_CACHE_ALIGN_BUFFER(struct rqt_box, rqt, sizeof(struct rqt_box));
313         int ret = -EINVAL;
314
315         memset(rqt, 0, sizeof(rqt));
316         memcpy(rqt, thor_rx_data_buf, sizeof(struct rqt_box));
317
318         debug("+RQT: %d, %d\n", rqt->rqt, rqt->rqt_data);
319
320         switch (rqt->rqt) {
321         case RQT_INFO:
322                 ret = process_rqt_info(rqt);
323                 break;
324         case RQT_CMD:
325                 ret = process_rqt_cmd(rqt);
326                 break;
327         case RQT_DL:
328                 ret = (int) process_rqt_download(rqt);
329                 break;
330         case RQT_UL:
331                 puts("RQT: UPLOAD not supported!\n");
332                 break;
333         default:
334                 error("unknown request (%d)", rqt->rqt);
335         }
336
337         return ret;
338 }
339
340 /* ********************************************************** */
341 /*         THOR USB Function                                  */
342 /* ********************************************************** */
343
344 static inline struct usb_endpoint_descriptor *
345 ep_desc(struct usb_gadget *g, struct usb_endpoint_descriptor *hs,
346         struct usb_endpoint_descriptor *fs)
347 {
348         if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH)
349                 return hs;
350         return fs;
351 }
352
353 static struct usb_interface_descriptor thor_downloader_intf_data = {
354         .bLength =              sizeof(thor_downloader_intf_data),
355         .bDescriptorType =      USB_DT_INTERFACE,
356
357         .bNumEndpoints =        2,
358         .bInterfaceClass =      USB_CLASS_CDC_DATA,
359 };
360
361 static struct usb_endpoint_descriptor fs_in_desc = {
362         .bLength =              USB_DT_ENDPOINT_SIZE,
363         .bDescriptorType =      USB_DT_ENDPOINT,
364
365         .bEndpointAddress =     USB_DIR_IN,
366         .bmAttributes = USB_ENDPOINT_XFER_BULK,
367 };
368
369 static struct usb_endpoint_descriptor fs_out_desc = {
370         .bLength =              USB_DT_ENDPOINT_SIZE,
371         .bDescriptorType =      USB_DT_ENDPOINT,
372
373         .bEndpointAddress =     USB_DIR_OUT,
374         .bmAttributes = USB_ENDPOINT_XFER_BULK,
375 };
376
377 /* CDC configuration */
378 static struct usb_interface_descriptor thor_downloader_intf_int = {
379         .bLength =              sizeof(thor_downloader_intf_int),
380         .bDescriptorType =      USB_DT_INTERFACE,
381
382         .bNumEndpoints =        1,
383         .bInterfaceClass =      USB_CLASS_COMM,
384          /* 0x02 Abstract Line Control Model */
385         .bInterfaceSubClass =   USB_CDC_SUBCLASS_ACM,
386         /* 0x01 Common AT commands */
387         .bInterfaceProtocol =   USB_CDC_ACM_PROTO_AT_V25TER,
388 };
389
390 static struct usb_cdc_header_desc thor_downloader_cdc_header = {
391         .bLength         =    sizeof(thor_downloader_cdc_header),
392         .bDescriptorType =    0x24, /* CS_INTERFACE */
393         .bDescriptorSubType = 0x00,
394         .bcdCDC =             0x0110,
395 };
396
397 static struct usb_cdc_call_mgmt_descriptor thor_downloader_cdc_call = {
398         .bLength         =    sizeof(thor_downloader_cdc_call),
399         .bDescriptorType =    0x24, /* CS_INTERFACE */
400         .bDescriptorSubType = 0x01,
401         .bmCapabilities =     0x00,
402         .bDataInterface =     0x01,
403 };
404
405 static struct usb_cdc_acm_descriptor thor_downloader_cdc_abstract = {
406         .bLength         =    sizeof(thor_downloader_cdc_abstract),
407         .bDescriptorType =    0x24, /* CS_INTERFACE */
408         .bDescriptorSubType = 0x02,
409         .bmCapabilities =     0x00,
410 };
411
412 static struct usb_cdc_union_desc thor_downloader_cdc_union = {
413         .bLength         =     sizeof(thor_downloader_cdc_union),
414         .bDescriptorType =     0x24, /* CS_INTERFACE */
415         .bDescriptorSubType =  USB_CDC_UNION_TYPE,
416 };
417
418 static struct usb_endpoint_descriptor fs_int_desc = {
419         .bLength = USB_DT_ENDPOINT_SIZE,
420         .bDescriptorType = USB_DT_ENDPOINT,
421
422         .bEndpointAddress = 3 | USB_DIR_IN,
423         .bmAttributes = USB_ENDPOINT_XFER_INT,
424         .wMaxPacketSize = __constant_cpu_to_le16(16),
425
426         .bInterval = 0x9,
427 };
428
429 static struct usb_interface_assoc_descriptor
430 thor_iad_descriptor = {
431         .bLength =              sizeof(thor_iad_descriptor),
432         .bDescriptorType =      USB_DT_INTERFACE_ASSOCIATION,
433
434         .bFirstInterface =      0,
435         .bInterfaceCount =      2,      /* control + data */
436         .bFunctionClass =       USB_CLASS_COMM,
437         .bFunctionSubClass =    USB_CDC_SUBCLASS_ACM,
438         .bFunctionProtocol =    USB_CDC_PROTO_NONE,
439 };
440
441 static struct usb_endpoint_descriptor hs_in_desc = {
442         .bLength =              USB_DT_ENDPOINT_SIZE,
443         .bDescriptorType =      USB_DT_ENDPOINT,
444
445         .bmAttributes = USB_ENDPOINT_XFER_BULK,
446         .wMaxPacketSize =       __constant_cpu_to_le16(512),
447 };
448
449 static struct usb_endpoint_descriptor hs_out_desc = {
450         .bLength =              USB_DT_ENDPOINT_SIZE,
451         .bDescriptorType =      USB_DT_ENDPOINT,
452
453         .bmAttributes = USB_ENDPOINT_XFER_BULK,
454         .wMaxPacketSize =       __constant_cpu_to_le16(512),
455 };
456
457 static struct usb_endpoint_descriptor hs_int_desc = {
458         .bLength = USB_DT_ENDPOINT_SIZE,
459         .bDescriptorType = USB_DT_ENDPOINT,
460
461         .bmAttributes = USB_ENDPOINT_XFER_INT,
462         .wMaxPacketSize = __constant_cpu_to_le16(16),
463
464         .bInterval = 0x9,
465 };
466
467 static struct usb_qualifier_descriptor dev_qualifier = {
468         .bLength =              sizeof(dev_qualifier),
469         .bDescriptorType =      USB_DT_DEVICE_QUALIFIER,
470
471         .bcdUSB =               __constant_cpu_to_le16(0x0200),
472         .bDeviceClass = USB_CLASS_VENDOR_SPEC,
473
474         .bNumConfigurations =   2,
475 };
476
477 /*
478  * This attribute vendor descriptor is necessary for correct operation with
479  * Windows version of THOR download program
480  *
481  * It prevents windows driver from sending zero lenght packet (ZLP) after
482  * each THOR_PACKET_SIZE. This assures consistent behaviour with libusb
483  */
484 static struct usb_cdc_attribute_vendor_descriptor thor_downloader_cdc_av = {
485         .bLength =              sizeof(thor_downloader_cdc_av),
486         .bDescriptorType =      0x24,
487         .bDescriptorSubType =   0x80,
488         .DAUType =              0x0002,
489         .DAULength =            0x0001,
490         .DAUValue =             0x00,
491 };
492
493 static const struct usb_descriptor_header *hs_thor_downloader_function[] = {
494         (struct usb_descriptor_header *)&thor_iad_descriptor,
495
496         (struct usb_descriptor_header *)&thor_downloader_intf_int,
497         (struct usb_descriptor_header *)&thor_downloader_cdc_header,
498         (struct usb_descriptor_header *)&thor_downloader_cdc_call,
499         (struct usb_descriptor_header *)&thor_downloader_cdc_abstract,
500         (struct usb_descriptor_header *)&thor_downloader_cdc_union,
501         (struct usb_descriptor_header *)&hs_int_desc,
502
503         (struct usb_descriptor_header *)&thor_downloader_intf_data,
504         (struct usb_descriptor_header *)&thor_downloader_cdc_av,
505         (struct usb_descriptor_header *)&hs_in_desc,
506         (struct usb_descriptor_header *)&hs_out_desc,
507         NULL,
508 };
509
510 /*-------------------------------------------------------------------------*/
511 static struct usb_request *alloc_ep_req(struct usb_ep *ep, unsigned length)
512 {
513         struct usb_request *req;
514
515         req = usb_ep_alloc_request(ep, 0);
516         if (!req)
517                 return req;
518
519         req->length = length;
520         req->buf = memalign(CONFIG_SYS_CACHELINE_SIZE, length);
521         if (!req->buf) {
522                 usb_ep_free_request(ep, req);
523                 req = NULL;
524         }
525
526         return req;
527 }
528
529 static int thor_rx_data(void)
530 {
531         struct thor_dev *dev = thor_func->dev;
532         int data_to_rx, tmp, status;
533
534         data_to_rx = dev->out_req->length;
535         tmp = data_to_rx;
536         do {
537                 dev->out_req->length = data_to_rx;
538                 debug("dev->out_req->length:%d dev->rxdata:%d\n",
539                       dev->out_req->length, dev->rxdata);
540
541                 status = usb_ep_queue(dev->out_ep, dev->out_req, 0);
542                 if (status) {
543                         error("kill %s:  resubmit %d bytes --> %d",
544                               dev->out_ep->name, dev->out_req->length, status);
545                         usb_ep_set_halt(dev->out_ep);
546                         return -EAGAIN;
547                 }
548
549                 while (!dev->rxdata) {
550                         usb_gadget_handle_interrupts();
551                         if (ctrlc())
552                                 return -1;
553                 }
554                 dev->rxdata = 0;
555                 data_to_rx -= dev->out_req->actual;
556         } while (data_to_rx);
557
558         return tmp;
559 }
560
561 static void thor_tx_data(unsigned char *data, int len)
562 {
563         struct thor_dev *dev = thor_func->dev;
564         unsigned char *ptr = dev->in_req->buf;
565         int status;
566
567         memset(ptr, 0, len);
568         memcpy(ptr, data, len);
569
570         dev->in_req->length = len;
571
572         debug("%s: dev->in_req->length:%d to_cpy:%d\n", __func__,
573               dev->in_req->length, sizeof(data));
574
575         status = usb_ep_queue(dev->in_ep, dev->in_req, 0);
576         if (status) {
577                 error("kill %s:  resubmit %d bytes --> %d",
578                       dev->in_ep->name, dev->in_req->length, status);
579                 usb_ep_set_halt(dev->in_ep);
580         }
581
582         /* Wait until tx interrupt received */
583         while (!dev->txdata)
584                 usb_gadget_handle_interrupts();
585
586         dev->txdata = 0;
587 }
588
589 static void thor_rx_tx_complete(struct usb_ep *ep, struct usb_request *req)
590 {
591         struct thor_dev *dev = thor_func->dev;
592         int status = req->status;
593
594         debug("%s: ep_ptr:%p, req_ptr:%p\n", __func__, ep, req);
595         switch (status) {
596         case 0:
597                 if (ep == dev->out_ep)
598                         dev->rxdata = 1;
599                 else
600                         dev->txdata = 1;
601
602                 break;
603
604         /* this endpoint is normally active while we're configured */
605         case -ECONNABORTED:             /* hardware forced ep reset */
606         case -ECONNRESET:               /* request dequeued */
607         case -ESHUTDOWN:                /* disconnect from host */
608         case -EREMOTEIO:                /* short read */
609         case -EOVERFLOW:
610                 error("ERROR:%d", status);
611                 break;
612         }
613
614         debug("%s complete --> %d, %d/%d\n", ep->name,
615               status, req->actual, req->length);
616 }
617
618 static struct usb_request *thor_start_ep(struct usb_ep *ep)
619 {
620         struct usb_request *req;
621
622         req = alloc_ep_req(ep, THOR_PACKET_SIZE);
623         debug("%s: ep:%p req:%p\n", __func__, ep, req);
624
625         if (!req)
626                 return NULL;
627
628         memset(req->buf, 0, req->length);
629         req->complete = thor_rx_tx_complete;
630
631         return req;
632 }
633
634 static void thor_setup_complete(struct usb_ep *ep, struct usb_request *req)
635 {
636         if (req->status || req->actual != req->length)
637                 debug("setup complete --> %d, %d/%d\n",
638                       req->status, req->actual, req->length);
639 }
640
641 static int
642 thor_func_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
643 {
644         struct thor_dev *dev = thor_func->dev;
645         struct usb_request *req = dev->req;
646         struct usb_gadget *gadget = dev->gadget;
647         int value = 0;
648
649         u16 len = le16_to_cpu(ctrl->wLength);
650
651         debug("Req_Type: 0x%x Req: 0x%x wValue: 0x%x wIndex: 0x%x wLen: 0x%x\n",
652               ctrl->bRequestType, ctrl->bRequest, ctrl->wValue, ctrl->wIndex,
653               ctrl->wLength);
654
655         switch (ctrl->bRequest) {
656         case USB_CDC_REQ_SET_CONTROL_LINE_STATE:
657                 value = 0;
658                 break;
659         case USB_CDC_REQ_SET_LINE_CODING:
660                 value = len;
661                 /* Line Coding set done = configuration done */
662                 thor_func->dev->configuration_done = 1;
663                 break;
664
665         default:
666                 error("thor_setup: unknown request: %d", ctrl->bRequest);
667         }
668
669         if (value >= 0) {
670                 req->length = value;
671                 req->zero = value < len;
672                 value = usb_ep_queue(gadget->ep0, req, 0);
673                 if (value < 0) {
674                         debug("%s: ep_queue: %d\n", __func__, value);
675                         req->status = 0;
676                 }
677         }
678
679         return value;
680 }
681
682 /* Specific to the THOR protocol */
683 static void thor_set_dma(void *addr, int len)
684 {
685         struct thor_dev *dev = thor_func->dev;
686
687         debug("in_req:%p, out_req:%p\n", dev->in_req, dev->out_req);
688         debug("addr:%p, len:%d\n", addr, len);
689
690         dev->out_req->buf = addr;
691         dev->out_req->length = len;
692 }
693
694 int thor_init(void)
695 {
696         struct thor_dev *dev = thor_func->dev;
697
698         /* Wait for a device enumeration and configuration settings */
699         debug("THOR enumeration/configuration setting....\n");
700         while (!dev->configuration_done)
701                 usb_gadget_handle_interrupts();
702
703         thor_set_dma(thor_rx_data_buf, strlen("THOR"));
704         /* detect the download request from Host PC */
705         if (thor_rx_data() < 0) {
706                 printf("%s: Data not received!\n", __func__);
707                 return -1;
708         }
709
710         if (!strncmp((char *)thor_rx_data_buf, "THOR", strlen("THOR"))) {
711                 puts("Download request from the Host PC\n");
712                 udelay(30 * 1000); /* 30 ms */
713
714                 strcpy((char *)thor_tx_data_buf, "ROHT");
715                 thor_tx_data(thor_tx_data_buf, strlen("ROHT"));
716         } else {
717                 puts("Wrong reply information\n");
718                 return -1;
719         }
720
721         return 0;
722 }
723
724 int thor_handle(void)
725 {
726         int ret;
727
728         /* receive the data from Host PC */
729         while (1) {
730                 thor_set_dma(thor_rx_data_buf, sizeof(struct rqt_box));
731                 ret = thor_rx_data();
732
733                 if (ret > 0) {
734                         ret = process_data();
735                         if (ret < 0)
736                                 return ret;
737                 } else {
738                         printf("%s: No data received!\n", __func__);
739                         break;
740                 }
741         }
742
743         return 0;
744 }
745
746 static int thor_func_bind(struct usb_configuration *c, struct usb_function *f)
747 {
748         struct usb_gadget *gadget = c->cdev->gadget;
749         struct f_thor *f_thor = func_to_thor(f);
750         struct thor_dev *dev;
751         struct usb_ep *ep;
752         int status;
753
754         thor_func = f_thor;
755         dev = memalign(CONFIG_SYS_CACHELINE_SIZE, sizeof(*dev));
756         if (!dev)
757                 return -ENOMEM;
758
759         memset(dev, 0, sizeof(*dev));
760         dev->gadget = gadget;
761         f_thor->dev = dev;
762
763         debug("%s: usb_configuration: 0x%p usb_function: 0x%p\n",
764               __func__, c, f);
765         debug("f_thor: 0x%p thor: 0x%p\n", f_thor, dev);
766
767         /* EP0  */
768         /* preallocate control response and buffer */
769         dev->req = usb_ep_alloc_request(gadget->ep0, 0);
770         if (!dev->req) {
771                 status = -ENOMEM;
772                 goto fail;
773         }
774         dev->req->buf = memalign(CONFIG_SYS_CACHELINE_SIZE,
775                                  gadget->ep0->maxpacket);
776         if (!dev->req->buf) {
777                 status = -ENOMEM;
778                 goto fail;
779         }
780
781         dev->req->complete = thor_setup_complete;
782
783         /* DYNAMIC interface numbers assignments */
784         status = usb_interface_id(c, f);
785
786         if (status < 0)
787                 goto fail;
788
789         thor_downloader_intf_int.bInterfaceNumber = status;
790         thor_downloader_cdc_union.bMasterInterface0 = status;
791
792         status = usb_interface_id(c, f);
793
794         if (status < 0)
795                 goto fail;
796
797         thor_downloader_intf_data.bInterfaceNumber = status;
798         thor_downloader_cdc_union.bSlaveInterface0 = status;
799
800         /* allocate instance-specific endpoints */
801         ep = usb_ep_autoconfig(gadget, &fs_in_desc);
802         if (!ep) {
803                 status = -ENODEV;
804                 goto fail;
805         }
806
807         if (gadget_is_dualspeed(gadget)) {
808                 hs_in_desc.bEndpointAddress =
809                                 fs_in_desc.bEndpointAddress;
810         }
811
812         dev->in_ep = ep; /* Store IN EP for enabling @ setup */
813
814         ep = usb_ep_autoconfig(gadget, &fs_out_desc);
815         if (!ep) {
816                 status = -ENODEV;
817                 goto fail;
818         }
819
820         if (gadget_is_dualspeed(gadget))
821                 hs_out_desc.bEndpointAddress =
822                                 fs_out_desc.bEndpointAddress;
823
824         dev->out_ep = ep; /* Store OUT EP for enabling @ setup */
825
826         ep = usb_ep_autoconfig(gadget, &fs_int_desc);
827         if (!ep) {
828                 status = -ENODEV;
829                 goto fail;
830         }
831
832         dev->int_ep = ep;
833
834         if (gadget_is_dualspeed(gadget)) {
835                 hs_int_desc.bEndpointAddress =
836                                 fs_int_desc.bEndpointAddress;
837
838                 f->hs_descriptors = (struct usb_descriptor_header **)
839                         &hs_thor_downloader_function;
840
841                 if (!f->hs_descriptors)
842                         goto fail;
843         }
844
845         debug("%s: out_ep:%p out_req:%p\n", __func__,
846               dev->out_ep, dev->out_req);
847
848         return 0;
849
850  fail:
851         free(dev);
852         return status;
853 }
854
855 static void free_ep_req(struct usb_ep *ep, struct usb_request *req)
856 {
857         free(req->buf);
858         usb_ep_free_request(ep, req);
859 }
860
861 static void thor_unbind(struct usb_configuration *c, struct usb_function *f)
862 {
863         struct f_thor *f_thor = func_to_thor(f);
864         struct thor_dev *dev = f_thor->dev;
865
866         free(dev);
867         memset(thor_func, 0, sizeof(*thor_func));
868         thor_func = NULL;
869 }
870
871 static void thor_func_disable(struct usb_function *f)
872 {
873         struct f_thor *f_thor = func_to_thor(f);
874         struct thor_dev *dev = f_thor->dev;
875
876         debug("%s:\n", __func__);
877
878         /* Avoid freeing memory when ep is still claimed */
879         if (dev->in_ep->driver_data) {
880                 free_ep_req(dev->in_ep, dev->in_req);
881                 usb_ep_disable(dev->in_ep);
882                 dev->in_ep->driver_data = NULL;
883         }
884
885         if (dev->out_ep->driver_data) {
886                 dev->out_req->buf = NULL;
887                 usb_ep_free_request(dev->out_ep, dev->out_req);
888                 usb_ep_disable(dev->out_ep);
889                 dev->out_ep->driver_data = NULL;
890         }
891
892         if (dev->int_ep->driver_data) {
893                 usb_ep_disable(dev->int_ep);
894                 dev->int_ep->driver_data = NULL;
895         }
896 }
897
898 static int thor_eps_setup(struct usb_function *f)
899 {
900         struct usb_composite_dev *cdev = f->config->cdev;
901         struct usb_gadget *gadget = cdev->gadget;
902         struct thor_dev *dev = thor_func->dev;
903         struct usb_endpoint_descriptor *d;
904         struct usb_request *req;
905         struct usb_ep *ep;
906         int result;
907
908         ep = dev->in_ep;
909         d = ep_desc(gadget, &hs_in_desc, &fs_in_desc);
910         debug("(d)bEndpointAddress: 0x%x\n", d->bEndpointAddress);
911
912         result = usb_ep_enable(ep, d);
913         if (result)
914                 goto exit;
915
916         ep->driver_data = cdev; /* claim */
917         req = thor_start_ep(ep);
918         if (!req) {
919                 usb_ep_disable(ep);
920                 result = -EIO;
921                 goto exit;
922         }
923
924         dev->in_req = req;
925         ep = dev->out_ep;
926         d = ep_desc(gadget, &hs_out_desc, &fs_out_desc);
927         debug("(d)bEndpointAddress: 0x%x\n", d->bEndpointAddress);
928
929         result = usb_ep_enable(ep, d);
930         if (result)
931                 goto exit;
932
933         ep->driver_data = cdev; /* claim */
934         req = thor_start_ep(ep);
935         if (!req) {
936                 usb_ep_disable(ep);
937                 result = -EIO;
938                 goto exit;
939         }
940
941         dev->out_req = req;
942         /* ACM control EP */
943         ep = dev->int_ep;
944         ep->driver_data = cdev; /* claim */
945
946  exit:
947         return result;
948 }
949
950 static int thor_func_set_alt(struct usb_function *f,
951                              unsigned intf, unsigned alt)
952 {
953         struct thor_dev *dev = thor_func->dev;
954         int result;
955
956         debug("%s: func: %s intf: %d alt: %d\n",
957               __func__, f->name, intf, alt);
958
959         switch (intf) {
960         case 0:
961                 debug("ACM INTR interface\n");
962                 break;
963         case 1:
964                 debug("Communication Data interface\n");
965                 result = thor_eps_setup(f);
966                 if (result)
967                         error("%s: EPs setup failed!", __func__);
968                 dev->configuration_done = 1;
969                 break;
970         }
971
972         return 0;
973 }
974
975 static int thor_func_init(struct usb_configuration *c)
976 {
977         struct f_thor *f_thor;
978         int status;
979
980         debug("%s: cdev: 0x%p\n", __func__, c->cdev);
981
982         f_thor = memalign(CONFIG_SYS_CACHELINE_SIZE, sizeof(*f_thor));
983         if (!f_thor)
984                 return -ENOMEM;
985
986         memset(f_thor, 0, sizeof(*f_thor));
987
988         f_thor->usb_function.name = "f_thor";
989         f_thor->usb_function.bind = thor_func_bind;
990         f_thor->usb_function.unbind = thor_unbind;
991         f_thor->usb_function.setup = thor_func_setup;
992         f_thor->usb_function.set_alt = thor_func_set_alt;
993         f_thor->usb_function.disable = thor_func_disable;
994
995         status = usb_add_function(c, &f_thor->usb_function);
996         if (status)
997                 free(f_thor);
998
999         return status;
1000 }
1001
1002 int thor_add(struct usb_configuration *c)
1003 {
1004         debug("%s:\n", __func__);
1005         return thor_func_init(c);
1006 }
1007
1008 DECLARE_GADGET_BIND_CALLBACK(usb_dnl_thor, thor_add);