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.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.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, 2010 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
// Contributors: jld
45
// Date:         2010-05-27
46
//
47
//####DESCRIPTIONEND####
48
//
49
//==========================================================================
50
#include <pkgconf/system.h>
51
 
52
#include <cyg/infra/cyg_type.h>
53
#include <cyg/infra/cyg_ass.h>
54
#include <cyg/infra/cyg_trac.h>
55
#include <cyg/infra/diag.h>
56
#include <cyg/io/devtab.h>
57
#include <cyg/hal/hal_arch.h>
58
#include <cyg/hal/drv_api.h>
59
#include <cyg/kernel/kapi.h>
60
 
61
#include <pkgconf/io_usb_slave_msd.h>
62
#include <cyg/io/usb/usbs_msd.h>
63
 
64
#ifdef CYGDAT_IO_USB_SLAVE_MSD0_SUB_CLASS_TYPE_SCSI
65
#include <cyg/io/usb/usbs_msd_scsi.h>
66
#endif
67
 
68
#include <string.h>
69
 
70
#if defined(CYGBLD_IO_USB_SLAVE_MSD_DEBUG)
71
#define DBG diag_printf
72
#else
73
#define DBG (1) ? (void)0 : diag_printf
74
#endif
75
 
76
#include CYGDAT_IO_USB_SLAVE_MSD_INL // Declaration of the Mass Storage devices
77
 
78
// --------------------------------------------------------------------------
79
// Create a USB String Descriptor from a C string.
80
//
81
void
82
usbs_msd_create_str_descriptor(char descr[], const char *str)
83
{
84
    cyg_uint32 i, n = strlen(str);
85
 
86
    if (n > (USB_MAX_STR_LEN/2 - 2))
87
        n = USB_MAX_STR_LEN/2 - 2;
88
 
89
    descr[0] = (cyg_uint8) (2*n + 2);
90
    descr[1] = USB_DEVREQ_DESCRIPTOR_TYPE_STRING;
91
 
92
    for (i=0; i<n; i++) {
93
        descr[i*2+2] = str[i];
94
        descr[i*2+3] = '\x00';
95
    }
96
}
97
 
98
// --------------------------------------------------------------------------
99
// Mass Storage Device Class Handler
100
//
101
static usbs_control_return
102
usbs_msd_class_handler(usbs_control_endpoint* ep0, void* callback_data)
103
{
104
  usbs_control_return result = USBS_CONTROL_RETURN_UNKNOWN;
105
  usb_devreq *req = (usb_devreq *) ep0->control_buffer;
106
  usbs_msd   *msd = (usbs_msd *) callback_data;
107
  static cyg_uint8 rsp_buf[32];
108
 
109
  DBG("USB MSD Class Handler: ");
110
 
111
  switch (req->request) {
112
 
113
    case USBS_MSD_CLASS_REQ_GET_MAX_LUN :
114
      DBG("USB MSD Request: Get MAX LUN %d\n", \
115
                                 msd->lun->max_lun);
116
      rsp_buf[0]  = msd->lun->max_lun - 1;
117
      ep0->buffer = rsp_buf;
118
      ep0->buffer_size = 1;
119
      result = USBS_CONTROL_RETURN_HANDLED;
120
      break;
121
 
122
    case USBS_MSD_CLASS_REQ_BOMSR :
123
      DBG("USB MSD Request: Reset\n");
124
      // FIXME : Handle Reset
125
      ep0->buffer_size = 0;
126
      result = USBS_CONTROL_RETURN_HANDLED;
127
      break;
128
 
129
    default :
130
      DBG("*** USB MSD Request: 0x%02X not implemented !***\n",
131
          (unsigned) req->request);
132
  }
133
 
134
  return result;
135
}
136
 
137
 
138
// --------------------------------------------------------------------------
139
// Callback for a USB state change
140
//
141
void
142
usbs_msd_state_change_handler(usbs_control_endpoint* ep, void* callback_data,
143
                                 usbs_state_change change, int prev_state)
144
{
145
  usbs_msd *msd = (usbs_msd *) callback_data;
146
 
147
#if defined(CYGBLD_IO_USB_SLAVE_MSD_DEBUG)
148
  const char *STATE_CHG_STR[] = { "Detached", "Attached", "Powered", "Reset",
149
                                  "Addressed", "Configured", "Deconfigured",
150
                                  "Suspended", "Resumed" };
151
 
152
  if (change > 0 && change < 10) {
153
    DBG("### %d:%s ###\n", change, STATE_CHG_STR[(int) change-1]);
154
  }
155
  else {
156
    DBG("### %d ###\n", change);
157
  }
158
#endif
159
 
160
  // Called from DSR, cond broadcast should be ok without mutex lock
161
  msd->usb_state = msd->ctrl_ep->state;
162
 
163
  cyg_cond_broadcast( &msd->state_cond );
164
 
165
  if (msd->app_state_change_fn)
166
    (*msd->app_state_change_fn)(ep, callback_data, change, prev_state);
167
 
168
}
169
 
170
 
171
// --------------------------------------------------------------------------
172
// Block the calling thread until the USB is configured.
173
 //
174
void
175
usbs_msd_wait_until_configured( usbs_msd* msd )
176
{
177
  cyg_mutex_lock( &msd->lock );
178
  while ( msd->usb_state != USBS_STATE_CONFIGURED )
179
    cyg_cond_wait( &msd->state_cond );
180
 
181
  // Dynamic end-points configuration
182
  if ( msd->static_ep == false )
183
  {
184
    msd->tx_ep = usbs_get_tx_endpoint( msd->ctrl_ep, msd->tx_ep_num );
185
    msd->rx_ep = usbs_get_rx_endpoint( msd->ctrl_ep, msd->rx_ep_num );
186
    DBG("tx_ep = %p\n", msd->tx_ep);
187
    DBG("rx_ep = %p\n", msd->rx_ep);
188
  }
189
 
190
  cyg_mutex_unlock( &msd->lock );
191
}
192
 
193
 
194
// --------------------------------------------------------------------------
195
// Determine if the device is currently configured.
196
//
197
cyg_bool
198
usbs_msd_is_configured( usbs_msd* msd )
199
{
200
  return msd->usb_state == USBS_STATE_CONFIGURED;
201
}
202
 
203
 
204
// --------------------------------------------------------------------------
205
// Callback for when a transmit / stall is complete
206
//
207
static void
208
usbs_msd_tx_complete( void *p, cyg_int32 result )
209
{
210
  usbs_msd* msd  = (usbs_msd*) p;
211
  msd->tx.result = result;
212
  cyg_semaphore_post( &msd->tx.ready );
213
}
214
 
215
 
216
// --------------------------------------------------------------------------
217
// Callback for when a receive / stall is complete
218
//
219
static void
220
usbs_msd_rx_complete( void *p, cyg_int32 result )
221
{
222
  usbs_msd* msd  = (usbs_msd*) p;
223
  msd->rx.result = result;
224
  cyg_semaphore_post( &msd->rx.ready );
225
}
226
 
227
 
228
// --------------------------------------------------------------------------
229
// Start an asynchronous transmit of a buffer.
230
//
231
static void
232
usbs_msd_start_tx(usbs_msd* msd, const void* buf, cyg_int32 n)
233
{
234
  usbs_start_tx_buffer( msd->tx_ep, (unsigned char*) buf, n,
235
                       usbs_msd_tx_complete, msd );
236
}
237
 
238
 
239
// --------------------------------------------------------------------------
240
// Block the caller until the transmit / stall is complete
241
//
242
static int
243
usbs_msd_wait_for_tx(usbs_msd* msd)
244
{
245
  cyg_semaphore_wait( &msd->tx.ready );
246
  return msd->tx.result;
247
}
248
 
249
 
250
// --------------------------------------------------------------------------
251
// Perform a synchronous transmit and wait for it to complete.
252
//
253
static cyg_int32
254
usbs_msd_tx(usbs_msd* msd, const void* buf, cyg_int32 n)
255
{
256
  usbs_msd_start_tx( msd, buf, n );
257
  return usbs_msd_wait_for_tx( msd );
258
}
259
 
260
 
261
// --------------------------------------------------------------------------
262
// Start an asynchronous receive of a buffer.
263
//
264
static void
265
usbs_msd_start_rx(usbs_msd* msd, void* buf, cyg_int32 n)
266
{
267
  usbs_start_rx_buffer( msd->rx_ep, (unsigned char*) buf, n,
268
                       usbs_msd_rx_complete, msd );
269
}
270
 
271
 
272
// --------------------------------------------------------------------------
273
// Block the caller until the receive / stall is complete
274
//
275
static cyg_int32
276
usbs_msd_wait_for_rx(usbs_msd* msd)
277
{
278
  cyg_semaphore_wait( &msd->rx.ready );
279
  return msd->rx.result;
280
}
281
 
282
 
283
// --------------------------------------------------------------------------
284
// Perform a synchronous receive and wait for it to complete
285
//
286
static cyg_int32
287
usbs_msd_rx(usbs_msd* msd, void* buf, cyg_int32 n)
288
{
289
  usbs_msd_start_rx( msd, buf, n );
290
  return usbs_msd_wait_for_rx( msd );
291
}
292
 
293
 
294
// --------------------------------------------------------------------------
295
// Halt end-point
296
//
297
static void
298
usbs_msd_set_ep_halted( usbs_msd* msd , usbs_msd_ep_t ep, cyg_bool state )
299
{
300
  if( ep == CYG_USBS_EP_RX )
301
    usbs_set_rx_endpoint_halted( msd->rx_ep , state );
302
  else if( ep == CYG_USBS_EP_TX )
303
    usbs_set_tx_endpoint_halted( msd->tx_ep , state );
304
}
305
 
306
 
307
// --------------------------------------------------------------------------
308
// Perform a synchronous end-point halt and wait for host to restart it
309
//
310
static cyg_int32
311
usbs_msd_ep_stall(usbs_msd* msd, usbs_msd_ep_t ep )
312
{
313
  cyg_sem_t *ready;
314
  cyg_int32 *result;
315
 
316
#if !defined(CYGSEM_IO_USB_SLAVE_MSD_STALL_ENABLE)
317
   return 1;
318
#endif
319
 
320
  if( ep == CYG_USBS_EP_RX )
321
  {
322
    ready    = &msd->rx.ready;
323
    result   = &msd->rx.result;
324
  }
325
  else if( ep == CYG_USBS_EP_TX )
326
  {
327
    ready    = &msd->tx.ready;
328
    result   = &msd->tx.result;
329
  }
330
  else
331
    return 0;
332
 
333
  // Halt End-point
334
  usbs_msd_set_ep_halted( msd, ep , 1 );
335
 
336
  // Wait
337
  if( ep == CYG_USBS_EP_RX )
338
    usbs_start_rx_endpoint_wait( msd->rx_ep, usbs_msd_rx_complete, msd );
339
  else if( ep == CYG_USBS_EP_TX )
340
    usbs_start_tx_endpoint_wait( msd->tx_ep, usbs_msd_tx_complete, msd );
341
 
342
  cyg_semaphore_wait( ready );
343
 
344
  return ( *result );
345
 
346
}
347
 
348
 
349
// --------------------------------------------------------------------------
350
// Initialize a Mass Storage Device structure
351
//
352
static bool
353
usbs_msd_init( usbs_msd* msd )
354
{
355
  cyg_io_handle_t handle;
356
  cyg_uint8 i = 0;
357
 
358
  if( msd->ctrl_ep == NULL )
359
    return false;
360
 
361
  // Lookup storage devices
362
  msd->lun->max_lun = 0;
363
  for (i = 0; i < USBS_MSD_CBW_MAX_LUN; i++)
364
  {
365
    if ( msd->lun->name[i] != NULL )
366
    {
367
      DBG("USB Slave MSD: Lookup %s \n", msd->lun->name[i] );
368
      if( cyg_io_lookup( msd->lun->name[i] , &handle ) != ENOERR )
369
        return false;
370
      msd->lun->handle[i] = handle;
371
      msd->lun->max_lun++;
372
    }
373
  }
374
 
375
  msd->tx.result =  0;
376
  msd->rx.result =  0;
377
 
378
  // Initialize TX and RX semaphore
379
  cyg_semaphore_init( &msd->tx.ready, 0 );
380
  cyg_semaphore_init( &msd->rx.ready, 0 );
381
 
382
  cyg_mutex_init( &msd->lock );
383
 
384
  cyg_cond_init( &msd->state_cond, &msd->lock );
385
 
386
  // Make USB string descriptors
387
  usbs_msd_create_str_descriptor( \
388
                     msd->enum_mfg_str,\
389
                     msd->mfg_str );
390
  usbs_msd_create_str_descriptor( \
391
                     msd->enum_product_str,\
392
                     msd->product_str );
393
  usbs_msd_create_str_descriptor( \
394
                     msd->enum_serial_str,\
395
                     msd->serial_str );
396
 
397
  // Set up enumeration & USB call-backs
398
  msd->usb_state = msd->ctrl_ep->state;
399
 
400
  msd->ctrl_ep->enumeration_data = msd->enum_data;
401
 
402
  if ( msd->ctrl_ep->state_change_fn )
403
    msd->app_state_change_fn = msd->ctrl_ep->state_change_fn;
404
 
405
  msd->ctrl_ep->state_change_fn    = usbs_msd_state_change_handler;
406
  msd->ctrl_ep->state_change_data  = (void*) msd;
407
  msd->ctrl_ep->class_control_fn   = usbs_msd_class_handler;
408
  msd->ctrl_ep->class_control_data = (void*) msd;
409
 
410
  if ( msd->handler_init )
411
     msd->handler_init( &msd->handler_data );
412
 
413
  msd->send    = usbs_msd_tx;
414
  msd->receive = usbs_msd_rx;
415
  msd->stall   = usbs_msd_ep_stall;
416
 
417
  // Setup initial state
418
  msd->state = CYG_USBS_MSD_WAIT;
419
 
420
  return true;
421
}
422
 
423
 
424
// --------------------------------------------------------------------------
425
// Initialize a Mass Storage Device structure
426
//
427
static void
428
usbs_msd_start_service(usbs_msd* msd)
429
{
430
 
431
  cyg_thread_create( USBS_MSD_THREAD_STACK_PRIORITY , &usbs_msd_handler, \
432
                     (cyg_addrword_t) msd, msd->serv_name, msd->serv_stack,  \
433
                     USBS_MSD_THREAD_STACK_SIZE, &msd->serv_handle, \
434
                     &msd->serv_thread);
435
 
436
  cyg_thread_resume( msd->serv_handle );
437
 
438
}
439
 
440
 
441
// --------------------------------------------------------------------------
442
// Start the USB subsystem
443
//
444
bool
445
usbs_msd_start(void)
446
{
447
 
448
#ifdef CYGPKG_IO_USB_SLAVE_MSD0
449
 
450
  DBG("USB Slave Mass-Storage 0 starts\n");
451
 
452
  if ( usbs_msd_init( &msd0 ) == false )
453
  {
454
    DBG("USB Slave Mass-Storage 0 startup failed\n");
455
    return false;
456
  }
457
 
458
  // ----- Start USB subsystem -----
459
  //
460
  usbs_start( msd0.ctrl_ep );
461
 
462
  usbs_msd_start_service( &msd0 );
463
 
464
#endif
465
 
466
  return true;
467
}
468
 
469
 
470
 
471
 

powered by: WebSVN 2.1.0

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