summaryrefslogtreecommitdiff
path: root/ecos/packages/io/usb/msd/slave/current/include/usbs_msd.h
blob: b0e6c4e8b266663d843bdf911e2d66c4d8f1624e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
#ifndef CYGONCE_USBS_MSD_H
#define CYGONCE_USBS_MSD_H
//==========================================================================
//
//      include/usbs_msd.h
//
//      Description of the USB slave-side MSD
//
//==========================================================================
// ####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 2008, 2010 Free Software Foundation, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later
// version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License
// along with eCos; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
//
// As a special exception, if other files instantiate templates or use
// macros or inline functions from this file, or you compile this file
// and link it with other works to produce a work based on this file,
// this file does not by itself cause the resulting work to be covered by
// the GNU General Public License. However the source code for this file
// must still be made available in accordance with section (3) of the GNU
// General Public License v2.
//
// This exception does not invalidate any other reasons why a work based
// on this file might be covered by the GNU General Public License.
// -------------------------------------------
// ####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s):    ccoutand
// Contributors:
// Date:         2010-06-03
// Purpose:
// Description:  USB slave-side MSD support
//
//
//####DESCRIPTIONEND####
//==========================================================================

#ifdef __cplusplus
extern "C" {
#endif

#include <cyg/infra/cyg_type.h>
#include <cyg/io/usb/usbs.h>

// ----------------------------------------------------------------------------
// The Mass Storage class requests
//
#define USBS_MSD_CLASS_REQ_ADSC          0x00
#define USBS_MSD_CLASS_REQ_GET_REQUEST   0xFC
#define USBS_MSD_CLASS_REQ_PUT_REQUEST   0xFD
#define USBS_MSD_CLASS_REQ_GET_MAX_LUN   0xFE
#define USBS_MSD_CLASS_REQ_BOMSR         0xFF

// ----------------------------------------------------------------------------
// Subclass values
//
#define USBS_MSD_SUB_CLASS_RBC           0x01 // Reduced Block Commands, typically for flash device
#define USBS_MSD_SUB_CLASS_SFF8020I      0x02 // For CDROM devices
#define USBS_MSD_SUB_CLASS_QIC_157       0x03 // QIC-157, Tape devices
#define USBS_MSD_SUB_CLASS_UFI           0x04 // For Floppy Drive Device
#define USBS_MSD_SUB_CLASS_SFF8070I      0x05 // For Floppy Drive Device
#define USBS_MSD_SUB_CLASS_SCSI          0x06 // SCSI transparent

#define USBS_MSD_DATA_IFACE_CLASS        0x8  // mass-storage

// ----------------------------------------------------------------------------
// Command Wrapper values
//
#define USBS_MSD_CSW_STATUS_PASSED       0x0
#define USBS_MSD_CSW_STATUS_FAILED       0x1

#define USBS_MSD_CBW_SIGNATURE           0x43425355
#define USBS_MSD_CSW_SIGNATURE           0x53425355

#define USBS_MSD_CBW_HOST2DEVICE         0x00
#define USBS_MSD_CBW_DEVICE2HOST         0x80

#define USBS_MSD_DEVICE_CLASS            0
#define USBS_MSD_NUM_IFACE               1
#define USBS_MSD_NUM_ENDP                2

// ----------------------------------------------------------------------------
// Helper macros
//
#define LO_BYTE_16(word16)          ((cyg_uint8) ((word16) & 0xFF))
#define HI_BYTE_16(word16)          ((cyg_uint8) (((word16) >> 8) & 0xFF))

#define BYTE0_32(word32)            ((cyg_uint8) ((word32) & 0xFF))
#define BYTE1_32(word32)            ((cyg_uint8) (((word32) >>  8) & 0xFF))
#define BYTE2_32(word32)            ((cyg_uint8) (((word32) >> 16) & 0xFF))
#define BYTE3_32(word32)            ((cyg_uint8) (((word32) >> 24) & 0xFF))

#define USB_CONFIGURATION_DESCRIPTOR_TOTAL_LENGTH(interfaces, endpoints) \
            (USB_CONFIGURATION_DESCRIPTOR_LENGTH +            \
            ((interfaces) * USB_INTERFACE_DESCRIPTOR_LENGTH) +  \
            ((endpoints)  * USB_ENDPOINT_DESCRIPTOR_LENGTH))

// ----------------------------------------------------------------------------
// Interface values
//
#define USBS_MSD_INTERFACE_PROTO          0x50 // Bulk mode

#define USBS_MSD_CBW_MAX_LUN               2
#define USBS_MSD_CBW_MIN_SCSI_CMD_LEN      1
#define USBS_MSD_CBW_MAX_SCSI_CMD_LEN     16

#define USBS_MSD_DISK_SECTOR_SIZE        512

// ----------------------------------------------------------------------------
// Mass Storage task constant
//
#define USBS_MSD_THREAD_STACK_SIZE       2048
#define USBS_MSD_THREAD_STACK_PRIORITY   15

// command block wrapper
typedef struct usbs_msd_cbw {
    cyg_uint32 signature;
    cyg_uint32 tag;
    cyg_uint32 data_transfert_len;
    cyg_uint8 flags;
    cyg_uint8 lun;
    struct cb {
      cyg_uint8 len;
      cyg_uint8 data[16];
    } cb;
} __attribute__((packed)) usbs_msd_cbw;

// command status wrapper
typedef struct usbs_msd_csw {
    cyg_uint32 signature;
    cyg_uint32 tag;
    cyg_uint32 data_residue;
    cyg_uint8  status;
} __attribute__((packed)) usbs_msd_csw;

// command block wrapper state
typedef enum {
    CYG_USBS_MSD_WAIT,
    CYG_USBS_MSD_DATA_IN,
    CYG_USBS_MSD_DATA_OUT
} usbs_msd_state_t;

// End-point type
typedef enum {
    CYG_USBS_EP0,
    CYG_USBS_EP_RX,
    CYG_USBS_EP_TX
} usbs_msd_ep_t;

// End-point status / control
typedef struct usbs_msd_ep_sc_t {
    cyg_sem_t   ready;
    cyg_int32   result;
} usbs_msd_ep_sc_t;

// Storage devices
typedef struct usbs_msd_lun {
    cyg_io_handle_t handle[USBS_MSD_CBW_MAX_LUN];
    const char    * name[USBS_MSD_CBW_MAX_LUN];
    cyg_uint8       max_lun;
} usbs_msd_lun;

typedef struct usbs_msd usbs_msd;

// Sub Class Handler
typedef cyg_int32 (*handler_cmd_fn)( usbs_msd * );
typedef bool (*handler_init_fn)(void **);

// End-point functions
typedef cyg_int32 (*send_fn)   ( usbs_msd *, const void * , cyg_int32 );
typedef cyg_int32 (*receive_fn)( usbs_msd *, const void * , cyg_int32 );
typedef cyg_int32 (*stall_fn)  ( usbs_msd* msd, usbs_msd_ep_t ep );

// Mass-storage device structure
struct usbs_msd {
    // Specify end-points to be used
    usbs_control_endpoint* ctrl_ep;
    usbs_tx_endpoint*   tx_ep;
    usbs_rx_endpoint*   rx_ep;

    cyg_uint8           tx_ep_num;
    cyg_uint8           rx_ep_num;

    cyg_bool            static_ep;

    // Enumeration data for this device
    usbs_enumeration_data* enum_data;

    // Enumeration string
    const char*         mfg_str;
    const char*         product_str;
    const char*         serial_str;
    char*               enum_mfg_str;
    char*               enum_product_str;
    char*               enum_serial_str;

    // End-point internal status/control
    usbs_msd_ep_sc_t    rx;
    usbs_msd_ep_sc_t    tx;

    // Lock for the state
    cyg_mutex_t         lock;

    // Condition variable for state changes
    cyg_cond_t          state_cond;

    // State of the USB interface
    cyg_uint32          usb_state;

    // Data transport-phase buffer
    cyg_uint8           buffer[USBS_MSD_DISK_SECTOR_SIZE];

    // State of the MSD
    usbs_msd_state_t    state;

    void (*app_state_change_fn)(struct usbs_control_endpoint*,
                                               void*, usbs_state_change, int);

    // Pointer to handler data
    void*               handler_data;

    // Commands Handler
    handler_cmd_fn      handler_cmd;

    // Initialize Command Handler
    handler_init_fn     handler_init;

    send_fn             send;
    receive_fn          receive;
    stall_fn            stall;

    // Mass-Storage Service
    char                serv_stack[USBS_MSD_THREAD_STACK_SIZE];
    cyg_handle_t        serv_handle;
    cyg_thread          serv_thread;
    char*               serv_name;

    // Storage Device
    usbs_msd_lun*       lun;

    // Command Block Wrapper
    usbs_msd_cbw        cbw;

    // Command Status Wrapper
    usbs_msd_csw        csw;
};

// ----------------------------------------------------------------------------
// A C interface to the MSD USB code.
// This is the interface for internal code

// Block the calling thread until the host configures the USB device.
void usbs_msd_wait_until_configured( usbs_msd* );

// Determines if the USB subsystem is configured
cyg_bool usbs_msd_is_configured( usbs_msd* );

// MSD main thread
void usbs_msd_handler( cyg_addrword_t );

#ifdef __cplusplus
} // extern "C"
#endif

#endif // CYGONCE_USBS_MSD_H