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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [io/] [usb/] [msd/] [slave/] [current/] [src/] [usbs_msd_handler.c] - Blame information for rev 825

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 786 skrzyp
//==========================================================================
2
//
3
//      usbs_msd_handler.c
4
//
5
//      Support for slave-side USB mass storage devices.
6
//
7
//==========================================================================
8
// ####ECOSGPLCOPYRIGHTBEGIN####
9
// -------------------------------------------
10
// This file is part of eCos, the Embedded Configurable Operating System.
11
// Copyright (C) 2008 Free Software Foundation, Inc.
12
//
13
// eCos is free software; you can redistribute it and/or modify it under
14
// the terms of the GNU General Public License as published by the Free
15
// Software Foundation; either version 2 or (at your option) any later
16
// version.
17
//
18
// eCos is distributed in the hope that it will be useful, but WITHOUT
19
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
21
// for more details.
22
//
23
// You should have received a copy of the GNU General Public License
24
// along with eCos; if not, write to the Free Software Foundation, Inc.,
25
// 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
26
//
27
// As a special exception, if other files instantiate templates or use
28
// macros or inline functions from this file, or you compile this file
29
// and link it with other works to produce a work based on this file,
30
// this file does not by itself cause the resulting work to be covered by
31
// the GNU General Public License. However the source code for this file
32
// must still be made available in accordance with section (3) of the GNU
33
// General Public License v2.
34
//
35
// This exception does not invalidate any other reasons why a work based
36
// on this file might be covered by the GNU General Public License.
37
// -------------------------------------------
38
// ####ECOSGPLCOPYRIGHTEND####
39
//==========================================================================
40
//#####DESCRIPTIONBEGIN####
41
//
42
// Author(s):    ccoutand
43
//
44
// Date:         2010-06-02
45
//
46
//####DESCRIPTIONEND####
47
//
48
//==========================================================================
49
 
50
#include <cyg/infra/cyg_type.h>
51
#include <cyg/infra/cyg_ass.h>
52
#include <cyg/infra/cyg_trac.h>
53
#include <cyg/infra/diag.h>
54
#include <cyg/hal/hal_arch.h>
55
#include <cyg/hal/hal_endian.h>
56
#include <cyg/hal/drv_api.h>
57
#include <cyg/kernel/kapi.h>
58
 
59
#include <pkgconf/io_usb_slave_msd.h>
60
#include <cyg/io/usb/usbs_msd.h>
61
 
62
#include <stdio.h> // for memcpy
63
 
64
#if defined(CYGBLD_IO_USB_SLAVE_MSD_DEBUG)
65
#define DBG diag_printf
66
#else
67
#define DBG (1) ? (void)0 : diag_printf
68
#endif
69
 
70
#if defined(CYGBLD_IO_USB_SLAVE_MSD_TRACE)
71
#define TRACE diag_printf
72
#else
73
#define TRACE (1) ? (void)0 : diag_printf
74
#endif
75
 
76
#define CONSTRUCT_CSW( _csw_, _tag_ ) \
77
{ \
78
   _csw_.tag = _tag_; \
79
   _csw_.signature = USBS_MSD_CSW_SIGNATURE; \
80
};
81
 
82
 
83
// Validate a command block wrapper
84
// CBW is sent from host in little endian format, hence it
85
// must be converted to the CPU endianness
86
//
87
static inline bool
88
usbs_msd_validate_cbw(usbs_msd_cbw *cbw, cyg_int32 len)
89
{
90
 
91
  // Convert to CPU endianness
92
  cbw->signature = CYG_LE32_TO_CPU( cbw->signature );
93
  cbw->tag       = CYG_LE32_TO_CPU( cbw->tag );
94
  cbw->data_transfert_len = CYG_LE32_TO_CPU( cbw->data_transfert_len );
95
 
96
  if( len != sizeof( usbs_msd_cbw ) ||
97
     cbw->signature != USBS_MSD_CBW_SIGNATURE )
98
  {
99
    DBG("USB Slave MSD: CBW signature %x, len %d\n\r", \
100
      cbw->signature, len);
101
    return false;
102
  }
103
  else
104
    return true;
105
}
106
 
107
 
108
// Validate a command block wrapper content
109
//
110
static inline bool
111
usbs_msd_validate_cbw_data(usbs_msd_cbw *cbw)
112
{
113
  if( ( cbw->lun < USBS_MSD_CBW_MAX_LUN ) && \
114
      ( cbw->cb.len <= USBS_MSD_CBW_MAX_SCSI_CMD_LEN ) && \
115
      ( cbw->cb.len >= USBS_MSD_CBW_MIN_SCSI_CMD_LEN ) && \
116
      ( ( cbw->flags == USBS_MSD_CBW_HOST2DEVICE ) || \
117
        ( cbw->flags == USBS_MSD_CBW_DEVICE2HOST ) ) )
118
  {
119
    return true;
120
  }
121
  else
122
  {
123
    DBG("USB Slave MSD: CBW Invalid data, LUN %d, len %d, flag %x\n\r", \
124
        cbw->lun, cbw->cb.len, cbw->flags);
125
  }
126
  return false;
127
}
128
 
129
 
130
// Send Command Status Wrapper
131
//
132
static inline cyg_int32
133
usbs_msd_send_csw( usbs_msd* msd )
134
{
135
  // Convert to host endianness
136
  msd->csw.signature = CYG_CPU_TO_LE32( msd->csw.signature );
137
  msd->csw.tag       = CYG_CPU_TO_LE32( msd->csw.tag );
138
  msd->csw.data_residue = CYG_CPU_TO_LE32( msd->csw.data_residue );
139
 
140
  return msd->send( msd, &msd->csw, sizeof( usbs_msd_csw ));
141
}
142
 
143
 
144
// Receive Command Status Wrapper
145
//
146
static cyg_int32
147
usbs_msd_wait_for_cbw( usbs_msd *msd )
148
{
149
  cyg_uint8 cbw[sizeof( usbs_msd_cbw ) + 1];
150
  cyg_int32 n;
151
 
152
  TRACE("USB Slave MSD: Wait for CBW\n\r");
153
  n = msd->receive( msd, cbw, sizeof( cbw ) );
154
 
155
  TRACE("USB Slave MSD: CBW received, len %d\n\r", n);
156
 
157
  if ( n < 0)
158
    return n;
159
 
160
  memcpy(&msd->cbw, cbw, sizeof( usbs_msd_cbw ));
161
 
162
  if ( ( true == usbs_msd_validate_cbw( &msd->cbw, n ) ) && \
163
          ( true == usbs_msd_validate_cbw_data( &msd->cbw ) ) )
164
  {
165
    CONSTRUCT_CSW( msd->csw , msd->cbw.tag );
166
 
167
    if( msd->cbw.flags == USBS_MSD_CBW_DEVICE2HOST )
168
    {
169
      msd->state = CYG_USBS_MSD_DATA_OUT;
170
    }
171
    else if ( msd->cbw.flags == USBS_MSD_CBW_HOST2DEVICE )
172
    {
173
      msd->state = CYG_USBS_MSD_DATA_IN;
174
    }
175
  }
176
 
177
  return n;
178
}
179
 
180
// USB slave side Mass-Storage Handler
181
//
182
void
183
usbs_msd_handler( cyg_addrword_t data )
184
{
185
  usbs_msd* msd = (usbs_msd*) data;
186
  cyg_int32 transfered = 0;
187
  cyg_int32 received   = 0;
188
 
189
  while(1)
190
  {
191
 
192
    // Wait for device to be configured
193
    DBG("USB Slave MSD: Wait for device configuration\n\r");
194
    usbs_msd_wait_until_configured( msd );
195
    cyg_thread_delay( (cyg_tick_count_t) 10 );
196
 
197
    while(1)
198
    {
199
 
200
      switch( msd->state )
201
      {
202
         case CYG_USBS_MSD_WAIT:
203
            // FIXME, check for return values
204
            // For the time being, -EPIPE and -EAGAIN triggers the
205
            // driver to wait for the device to be configured again.
206
            received = usbs_msd_wait_for_cbw( msd );
207
            if ( received < 0 )
208
              break;
209
            // Fall through
210
 
211
         case CYG_USBS_MSD_DATA_IN:
212
         case CYG_USBS_MSD_DATA_OUT:
213
            // Handle data transfer IN and OUT
214
            transfered = msd->handler_cmd( msd );
215
 
216
            // Data transfer failed because of -EPIPE or -EAGAIN. For
217
            // the time being just wait for the device to be re-configured
218
            if(transfered < 0)
219
            {
220
              DBG("USB Slave MSD: Data transfer error\n\r");
221
              msd->state = CYG_USBS_MSD_WAIT;
222
              break;
223
            }
224
 
225
            // Compute the data residue value to be recorded in the
226
            // Command Status Wrapper
227
            msd->csw.data_residue = msd->cbw.data_transfert_len - transfered;
228
 
229
            // Check if all data has been transfered / received to / from
230
            // the host
231
            if( msd->csw.data_residue != 0 )
232
            {
233
              DBG("USB Slave MSD: Transfer not complete %d / %d\n\r", \
234
                        msd->cbw.data_transfert_len, transfered);
235
 
236
              // Stall endpoint, this is a waiting call until the host has
237
              // cleared the stall. AT91 USB driver does not seem to handle
238
              // it!
239
              msd->stall( msd, CYG_USBS_EP_TX );
240
#if defined(CYGSEM_IO_USB_SLAVE_MSD_STALL_ENABLE)
241
              TRACE("USB Slave MSD: Stall completed\n\r");
242
#endif
243
            }
244
 
245
            // Complete the transaction by sending the command status
246
            usbs_msd_send_csw( msd );
247
 
248
            TRACE("USB Slave MSD: CSW sent\n\r");
249
 
250
            // Wait for next command
251
            msd->state = CYG_USBS_MSD_WAIT;
252
            break;
253
 
254
         default:
255
            DBG("USB Slave MSD: Invalid state\n\r");
256
            break;
257
      }
258
 
259
      if( ( transfered < 0 ) || ( received < 0 ) )
260
        break;
261
 
262
    }
263
  }
264
}
265
 
266
 

powered by: WebSVN 2.1.0

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