OpenCores
URL https://opencores.org/ocsvn/usb_device_core/usb_device_core/trunk

Subversion Repositories usb_device_core

[/] [usb_device_core/] [trunk/] [sw/] [usb_device.c] - Blame information for rev 5

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 5 ultra_embe
//-----------------------------------------------------------------
2
//                         USB CDC Device SW
3
//                               V0.1
4
//                         Ultra-Embedded.com
5
//                          Copyright 2014
6
//
7
//                  Email: admin@ultra-embedded.com
8
//
9
//                          License: GPL
10
// If you would like a version with a more permissive license for use in
11
// closed source commercial applications please contact me for details.
12
//-----------------------------------------------------------------
13
//
14
// This file is part of USB CDC Device SW.
15
//
16
// USB CDC Device SW is free software; you can redistribute it and/or modify
17
// it under the terms of the GNU General Public License as published by
18
// the Free Software Foundation; either version 2 of the License, or
19
// (at your option) any later version.
20
//
21
// USB CDC Device SW is distributed in the hope that it will be useful,
22
// but WITHOUT ANY WARRANTY; without even the implied warranty of
23
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24
// GNU General Public License for more details.
25
//
26
// You should have received a copy of the GNU General Public License
27
// along with USB CDC Device SW; if not, write to the Free Software
28
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29
//-----------------------------------------------------------------
30
#include <string.h>
31
#include "usb_device.h"
32
#include "usb_desc.h"
33
#include "usb_log.h"
34
#include "usbf_defs.h"
35
#include "usbf_hw.h"
36
 
37
//-----------------------------------------------------------------
38
// Defines:
39
//-----------------------------------------------------------------
40
#define USB_CTRL_TX_TIMEOUT     100
41
 
42
#ifndef MAX_CTRL_DATA_LENGTH
43
    #define MAX_CTRL_DATA_LENGTH    64
44
#endif
45
 
46
//-----------------------------------------------------------------
47
// Types
48
//-----------------------------------------------------------------
49
 
50
// SETUP packet data format
51
struct device_request
52
{
53
        unsigned char   bmRequestType;
54
        unsigned char   bRequest;
55
        unsigned short  wValue;
56
        unsigned short  wIndex;
57
        unsigned short  wLength;
58
};
59
 
60
struct control_transfer
61
{
62
    // SETUP packet
63
        struct device_request   request;
64
 
65
    // Data (OUT) stage expected?
66
    int                     data_expected;
67
 
68
    // Data buffer
69
    unsigned char           data_buffer[MAX_CTRL_DATA_LENGTH];
70
 
71
    // Data received index
72
    int                     data_idx;
73
};
74
 
75
//-----------------------------------------------------------------
76
// Locals:
77
//-----------------------------------------------------------------
78
static struct control_transfer  _ctrl_xfer;
79
static int                      _remote_wake_enabled;
80
static FP_CLASS_REQUEST         _class_request;
81
 
82
//-----------------------------------------------------------------
83
// get_status:
84
//-----------------------------------------------------------------
85
static void get_status(struct device_request *request)
86
{
87
        unsigned char bRecipient = request->bmRequestType & USB_RECIPIENT_MASK;
88
    unsigned char data[2] = {0, 0};
89
 
90
    log_printf(USBLOG_INFO, "USB: Get Status %x\n", bRecipient);
91
 
92
        if ( bRecipient == USB_RECIPIENT_DEVICE )
93
        {
94
        // Self-powered
95
                if (!usb_is_bus_powered())
96
            data[0] |= (1 << 0);
97
 
98
        // Remote Wake-up enabled
99
                if (_remote_wake_enabled)
100
            data[0] |= (1 << 1);
101
 
102
                usb_control_send( data, 2, request->wLength );
103
        }
104
        else if ( bRecipient == USB_RECIPIENT_INTERFACE )
105
        {
106
                usb_control_send( data, 2, request->wLength );
107
        }
108
        else if ( bRecipient == USB_RECIPIENT_ENDPOINT )
109
        {
110
                if (usbhw_is_endpoint_stalled( request->wIndex & ENDPOINT_ADDR_MASK))
111
            data[0] = 1;
112
                usb_control_send( data, 2, request->wLength );
113
        }
114
        else
115
        usbhw_control_endpoint_stall();
116
}
117
//-----------------------------------------------------------------
118
// clear_feature:
119
//-----------------------------------------------------------------
120
static void clear_feature(struct device_request *request)
121
{
122
        unsigned char bRecipient = request->bmRequestType & USB_RECIPIENT_MASK;
123
 
124
    log_printf(USBLOG_INFO, "USB: Clear Feature %x\n", bRecipient);
125
 
126
        if ( bRecipient == USB_RECIPIENT_DEVICE )
127
        {
128
                if ( request->wValue == USB_FEATURE_REMOTE_WAKEUP )
129
                {
130
            log_printf(USBLOG_INFO, "USB: Disable remote wake\n");
131
            _remote_wake_enabled = 0;
132
                        usbhw_control_endpoint_ack();
133
                }
134
                else if ( request->wValue == USB_FEATURE_TEST_MODE )
135
                {
136
            log_printf(USBLOG_INFO, "USB: Disable test mode\n");
137
                        usbhw_control_endpoint_ack();
138
                }
139
                else
140
            usbhw_control_endpoint_stall();
141
        }
142
        else if ( bRecipient == USB_RECIPIENT_ENDPOINT &&
143
                          request->wValue == USB_FEATURE_ENDPOINT_STATE )
144
        {
145
                usbhw_control_endpoint_ack();
146
                usbhw_clear_endpoint_stall( request->wIndex & ENDPOINT_ADDR_MASK );
147
        }
148
        else
149
        usbhw_control_endpoint_stall();
150
}
151
//-----------------------------------------------------------------
152
// set_feature:
153
//-----------------------------------------------------------------
154
static void set_feature(struct device_request *request)
155
{
156
        unsigned char bRecipient = request->bmRequestType & USB_RECIPIENT_MASK;
157
 
158
    log_printf(USBLOG_INFO, "USB: Set Feature %x\n", bRecipient);
159
 
160
        if ( bRecipient == USB_RECIPIENT_DEVICE )
161
        {
162
                if ( request->wValue == USB_FEATURE_REMOTE_WAKEUP )
163
                {
164
            log_printf(USBLOG_INFO, "USB: Enable remote wake\n");
165
            _remote_wake_enabled = 1;
166
                        usbhw_control_endpoint_ack();
167
                }
168
                else if ( request->wValue == USB_FEATURE_TEST_MODE )
169
                {
170
            log_printf(USBLOG_INFO, "USB: Enable test mode\n");
171
                        usbhw_control_endpoint_ack();
172
                }
173
                else
174
            usbhw_control_endpoint_stall();
175
        }
176
        else if ( bRecipient == USB_RECIPIENT_ENDPOINT &&
177
                          request->wValue == USB_FEATURE_ENDPOINT_STATE )
178
        {
179
                usbhw_control_endpoint_ack();
180
                usbhw_set_endpoint_stall(request->wIndex & ENDPOINT_ADDR_MASK);
181
        }
182
        else
183
        usbhw_control_endpoint_stall();
184
}
185
//-----------------------------------------------------------------
186
// set_address:
187
//-----------------------------------------------------------------
188
static void set_address(struct device_request *request)
189
{
190
        unsigned char addr = (LO_BYTE(request->wValue)) & USB_ADDRESS_MASK;
191
 
192
        usbhw_set_address(addr);
193
    usbhw_control_endpoint_ack();
194
 
195
    log_printf(USBLOG_INFO, "USB: Set address %x\n", addr);
196
}
197
//-----------------------------------------------------------------
198
// get_descriptor:
199
//-----------------------------------------------------------------
200
static void get_descriptor(struct device_request *request)
201
{
202
        unsigned char  bDescriptorType = HI_BYTE(request->wValue);
203
        unsigned char  bDescriptorIndex = LO_BYTE( request->wValue );
204
        unsigned short wLength = request->wLength;
205
        unsigned char  bCount = 0;
206
    unsigned char *desc_ptr;
207
 
208
    desc_ptr = usb_get_descriptor(bDescriptorType, bDescriptorIndex, wLength, &bCount);
209
 
210
    if (desc_ptr)
211
        usb_control_send(desc_ptr, bCount, request->wLength);
212
    else
213
        usbhw_control_endpoint_stall();
214
}
215
//-----------------------------------------------------------------
216
// get_configuration:
217
//-----------------------------------------------------------------
218
static void get_configuration(struct device_request *request)
219
{
220
        unsigned char conf = usbhw_is_configured() ? 1 : 0;
221
 
222
    log_printf(USBLOG_INFO, "USB: Get configuration %x\n", conf);
223
 
224
        usb_control_send( &conf, 1, request->wLength );
225
}
226
//-----------------------------------------------------------------
227
// set_configuration:
228
//-----------------------------------------------------------------
229
static void set_configuration(struct device_request *request)
230
{
231
    log_printf(USBLOG_INFO, "USB: set_configuration %x\n", request->wValue);
232
 
233
        if ( request->wValue == 0 )
234
        {
235
                usbhw_control_endpoint_ack();
236
        usbhw_set_configured(0);
237
        }
238
    // Only support one configuration for now
239
        else if ( request->wValue == 1 )
240
        {
241
                usbhw_control_endpoint_ack();
242
        usbhw_set_configured(1);
243
        }
244
        else
245
        usbhw_control_endpoint_stall();
246
}
247
//-----------------------------------------------------------------
248
// get_interface:
249
//-----------------------------------------------------------------
250
static void get_interface(struct device_request *request)
251
{
252
    log_printf(USBLOG_INFO, "USB: Get interface\n");
253
        usbhw_control_endpoint_stall();
254
}
255
//-----------------------------------------------------------------
256
// set_interface:
257
//-----------------------------------------------------------------
258
static void set_interface(struct device_request *request)
259
{
260
    log_printf(USBLOG_INFO, "USB: set_interface %x %x\n", request->wValue, request->wIndex);
261
 
262
        if ( request->wValue == 0 && request->wIndex == 0 )
263
                usbhw_control_endpoint_ack();
264
        else
265
        usbhw_control_endpoint_stall();
266
}
267
 
268
//-----------------------------------------------------------------
269
// usb_process_request:
270
//-----------------------------------------------------------------
271
static void usb_process_request(struct device_request *request, unsigned char type, unsigned char req, unsigned char *data)
272
{
273
        if ( type == USB_STANDARD_REQUEST )
274
        {
275
        // Standard requests
276
        switch (req)
277
        {
278
        case REQ_GET_STATUS:
279
            get_status(request);
280
            break;
281
        case REQ_CLEAR_FEATURE:
282
            clear_feature(request);
283
            break;
284
        case REQ_SET_FEATURE:
285
            set_feature(request);
286
            break;
287
        case REQ_SET_ADDRESS:
288
            set_address(request);
289
            break;
290
        case REQ_GET_DESCRIPTOR:
291
            get_descriptor(request);
292
            break;
293
        case REQ_GET_CONFIGURATION:
294
            get_configuration(request);
295
            break;
296
        case REQ_SET_CONFIGURATION:
297
            set_configuration(request);
298
            break;
299
        case REQ_GET_INTERFACE:
300
            get_interface(request);
301
            break;
302
        case REQ_SET_INTERFACE:
303
            set_interface(request);
304
            break;
305
        default:
306
            log_printf(USBLOG_ERR, "USB: Unknown standard request %x\n", req);
307
                    usbhw_control_endpoint_stall();
308
            break;
309
        }
310
        }
311
        else if ( type == USB_VENDOR_REQUEST )
312
        {
313
        log_printf(USBLOG_ERR, "Vendor: Unknown command\n");
314
 
315
        // None supported
316
                usbhw_control_endpoint_stall();
317
        }
318
        else if ( type == USB_CLASS_REQUEST && _class_request)
319
        {
320
        _class_request(req, request->wValue, request->wIndex, data, request->wLength);
321
        }
322
        else
323
        usbhw_control_endpoint_stall();
324
}
325
//-----------------------------------------------------------------
326
// usb_process_setup: Process SETUP packet
327
//-----------------------------------------------------------------
328
static void usb_process_setup(void)
329
{
330
    unsigned char type, req;
331
    unsigned char setup_pkt[EP0_MAX_PACKET_SIZE];
332
 
333
        usbhw_get_rx_data(ENDPOINT_CONTROL, setup_pkt, EP0_MAX_PACKET_SIZE);
334
    usbhw_clear_rx_ready(ENDPOINT_CONTROL);
335
 
336
    #if (LOG_LEVEL >= USBLOG_SETUP_DATA)
337
    {
338
        int i;
339
 
340
        log_printf(USBLOG_SETUP_DATA, "USB: SETUP data %d\n", EP0_MAX_PACKET_SIZE);
341
 
342
        for (i=0;i<EP0_MAX_PACKET_SIZE;i++)
343
            log_printf(USBLOG_SETUP_DATA, "%02x ", setup_pkt[i]);
344
 
345
        log_printf(USBLOG_SETUP_DATA, "\n");
346
    }
347
    #endif
348
 
349
    // Extract packet to local endian format
350
    _ctrl_xfer.request.bmRequestType = setup_pkt[0];
351
    _ctrl_xfer.request.bRequest      = setup_pkt[1];
352
    _ctrl_xfer.request.wValue        = setup_pkt[3];
353
    _ctrl_xfer.request.wValue      <<= 8;
354
    _ctrl_xfer.request.wValue       |= setup_pkt[2];
355
    _ctrl_xfer.request.wIndex        = setup_pkt[5];
356
    _ctrl_xfer.request.wIndex      <<= 8;
357
    _ctrl_xfer.request.wIndex       |= setup_pkt[4];
358
    _ctrl_xfer.request.wLength       = setup_pkt[7];
359
    _ctrl_xfer.request.wLength     <<= 8;
360
    _ctrl_xfer.request.wLength      |= setup_pkt[6];
361
 
362
        _ctrl_xfer.data_idx      = 0;
363
    _ctrl_xfer.data_expected = 0;
364
 
365
        type = _ctrl_xfer.request.bmRequestType & USB_REQUEST_TYPE_MASK;
366
        req  = _ctrl_xfer.request.bRequest;
367
 
368
    // SETUP - GET
369
        if (_ctrl_xfer.request.bmRequestType & ENDPOINT_DIR_IN)
370
        {
371
        log_printf(USBLOG_SETUP, "USB: SETUP Get wValue=0x%x wIndex=0x%x wLength=%d\n",
372
                                    _ctrl_xfer.request.wValue,
373
                                    _ctrl_xfer.request.wIndex,
374
                                    _ctrl_xfer.request.wLength);
375
 
376
                usb_process_request(&_ctrl_xfer.request, type, req, _ctrl_xfer.data_buffer);
377
        }
378
    // SETUP - SET
379
        else
380
        {
381
        // No data
382
                if ( _ctrl_xfer.request.wLength == 0 )
383
        {
384
            log_printf(USBLOG_SETUP, "USB: SETUP Set wValue=0x%x wIndex=0x%x wLength=%d\n",
385
                                        _ctrl_xfer.request.wValue,
386
                                        _ctrl_xfer.request.wIndex,
387
                                        _ctrl_xfer.request.wLength);
388
            usb_process_request(&_ctrl_xfer.request, type, req, _ctrl_xfer.data_buffer);
389
        }
390
        // Data expected
391
                else
392
                {
393
            log_printf(USBLOG_SETUP, "USB: SETUP Set wValue=0x%x wIndex=0x%x wLength=%d [OUT expected]\n",
394
                                        _ctrl_xfer.request.wValue,
395
                                        _ctrl_xfer.request.wIndex,
396
                                        _ctrl_xfer.request.wLength);
397
 
398
                        if ( _ctrl_xfer.request.wLength <= MAX_CTRL_DATA_LENGTH )
399
            {
400
                // OUT packets expected to follow containing data
401
                                _ctrl_xfer.data_expected = 1;
402
            }
403
            // Error: Too much data!
404
                        else
405
                        {
406
                log_printf(USBLOG_ERR, "USB: More data than max transfer size\n");
407
                usbhw_control_endpoint_stall();
408
                        }
409
                }
410
        }
411
}
412
//-----------------------------------------------------------------
413
// usb_process_out: Process OUT (on control EP0)
414
//-----------------------------------------------------------------
415
static void usb_process_out(void)
416
{
417
        unsigned short received;
418
    unsigned char type;
419
    unsigned char req;
420
 
421
    // Error: Not expecting DATA-OUT!
422
        if (!_ctrl_xfer.data_expected)
423
        {
424
        log_printf(USBLOG_ERR, "USB: (EP0) OUT received but not expected, STALL\n");
425
                usbhw_control_endpoint_stall();
426
        }
427
        else
428
        {
429
                received = usbhw_get_rx_count( ENDPOINT_CONTROL );
430
 
431
        log_printf(USBLOG_SETUP_OUT, "USB: OUT received (%d bytes)\n", received);
432
 
433
                if ( (_ctrl_xfer.data_idx + received) > MAX_CTRL_DATA_LENGTH )
434
                {
435
            log_printf(USBLOG_ERR, "USB: Too much OUT EP0 data %d > %d, STALL\n", (_ctrl_xfer.data_idx + received), MAX_CTRL_DATA_LENGTH);
436
                        usbhw_control_endpoint_stall();
437
                }
438
                else
439
                {
440
                        usbhw_get_rx_data(ENDPOINT_CONTROL, &_ctrl_xfer.data_buffer[_ctrl_xfer.data_idx], received);
441
            usbhw_clear_rx_ready(ENDPOINT_CONTROL);
442
                        _ctrl_xfer.data_idx += received;
443
 
444
            log_printf(USBLOG_SETUP_OUT, "USB: OUT packet re-assembled %d\n", _ctrl_xfer.data_idx);
445
 
446
            // End of transfer (short transfer received?)
447
                    if (received < EP0_MAX_PACKET_SIZE || _ctrl_xfer.data_idx >= _ctrl_xfer.request.wLength)
448
                    {
449
                // Send ZLP (ACK for Status stage)
450
                log_printf(USBLOG_SETUP_OUT, "USB: Send ZLP status stage %d %d\n", _ctrl_xfer.data_idx, _ctrl_xfer.request.wLength);
451
 
452
                usbhw_load_tx_buffer( ENDPOINT_CONTROL, 0, 0);
453
                            while (!usbhw_has_tx_space( ENDPOINT_CONTROL ))
454
                    ;
455
                            _ctrl_xfer.data_expected = 0;
456
 
457
                    type = _ctrl_xfer.request.bmRequestType & USB_REQUEST_TYPE_MASK;
458
                    req  = _ctrl_xfer.request.bRequest;
459
 
460
                            usb_process_request(&_ctrl_xfer.request, type, req, _ctrl_xfer.data_buffer);
461
                    }
462
            else
463
                log_printf(USBLOG_SETUP_OUT, "DEV: More data expected!\n");
464
        }
465
        }
466
}
467
//-----------------------------------------------------------------
468
// usb_control_send: Perform a transfer via IN
469
//-----------------------------------------------------------------
470
int usb_control_send(unsigned char *buf, int size, int requested_size)
471
{
472
        t_time tS;
473
        int send;
474
        int remain;
475
        int count = 0;
476
    int err = 0;
477
 
478
    log_printf(USBLOG_SETUP_IN, "USB: usb_control_send %d\n", size);
479
 
480
    // Loop until partial packet sent
481
    do
482
        {
483
                remain = size - count;
484
                send = MIN(remain, EP0_MAX_PACKET_SIZE);
485
 
486
        log_printf(USBLOG_SETUP_IN_DBG, " Remain %d, Send %d\n", remain, send);
487
 
488
        // Do not send ZLP if requested size was size transferred
489
        if (remain == 0 && size == requested_size)
490
            break;
491
 
492
                usbhw_load_tx_buffer(ENDPOINT_CONTROL, buf, (unsigned char) send);
493
 
494
                buf += send;
495
                count += send;
496
 
497
        log_printf(USBLOG_SETUP_IN_DBG, " Sent %d, Remain %d\n", send, (size - count));
498
 
499
                tS = usbhw_timer_now();
500
                while ( !usbhw_has_tx_space( ENDPOINT_CONTROL ) )
501
                {
502
            if (usbhw_timer_diff(usbhw_timer_now(), tS) > USB_CTRL_TX_TIMEOUT)
503
                        {
504
                log_printf(USBLOG_ERR, "USB: Timeout sending IN data\n");
505
                err = 1;
506
                                break;
507
                        }
508
 
509
            // Give up on early OUT (STATUS stage)
510
            if (usbhw_is_rx_ready(ENDPOINT_CONTROL))
511
            {
512
                log_printf(USBLOG_ERR, "USB: Early ACK received...\n");
513
                break;
514
            }
515
                }
516
        }
517
    while (send >= EP0_MAX_PACKET_SIZE);
518
 
519
    if (!err)
520
    {
521
        log_printf(USBLOG_SETUP_IN, "USB: Sent total %d\n", count);
522
 
523
            // Wait for ACK from host
524
            tS = usbhw_timer_now();
525
            do
526
        {
527
            if (usbhw_timer_diff(usbhw_timer_now(), tS) > USB_CTRL_TX_TIMEOUT)
528
                    {
529
                            log_printf(USBLOG_ERR, "USB: ACK not received\n");
530
                err = 1;
531
                            break;
532
                    }
533
            }
534
        while (!usbhw_is_rx_ready(ENDPOINT_CONTROL));
535
 
536
        usbhw_clear_rx_ready(ENDPOINT_CONTROL);
537
 
538
        if (!err)
539
        {
540
            log_printf(USBLOG_SETUP_IN, "USB: ACK received\n");
541
        }
542
    }
543
 
544
    return !err;
545
}
546
//-----------------------------------------------------------------
547
// usbf_init:
548
//-----------------------------------------------------------------
549
void usbf_init(unsigned int base, FP_BUS_RESET bus_reset, FP_CLASS_REQUEST class_request)
550
{
551
    _class_request = class_request;
552
    usbhw_init(base, bus_reset, usb_process_setup, usb_process_out);
553
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.