~pmdj/ubuntu/trusty/qemu/2.9+applesmc+fadtv3

« back to all changes in this revision

Viewing changes to roms/u-boot/drivers/usb/gadget/f_thor.c

  • Committer: Phil Dennis-Jordan
  • Date: 2017-07-21 08:03:43 UTC
  • mfrom: (1.1.1)
  • Revision ID: phil@philjordan.eu-20170721080343-2yr2vdj7713czahv
New upstream release 2.9.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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);