GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usbx_host_classes/src/ux_host_class_storage_media_capacity_get.c Lines: 31 31 100.0 %
Date: 2024-12-12 17:16:36 Branches: 13 13 100.0 %

Line Branch Exec Source
1
/***************************************************************************
2
 * Copyright (c) 2024 Microsoft Corporation
3
 *
4
 * This program and the accompanying materials are made available under the
5
 * terms of the MIT License which is available at
6
 * https://opensource.org/licenses/MIT.
7
 *
8
 * SPDX-License-Identifier: MIT
9
 **************************************************************************/
10
11
12
/**************************************************************************/
13
/**************************************************************************/
14
/**                                                                       */
15
/** USBX Component                                                        */
16
/**                                                                       */
17
/**   Storage Class                                                       */
18
/**                                                                       */
19
/**************************************************************************/
20
/**************************************************************************/
21
22
23
/* Include necessary system files.  */
24
25
#define UX_SOURCE_CODE
26
27
#include "ux_api.h"
28
#include "ux_host_class_storage.h"
29
#include "ux_host_stack.h"
30
31
32
/**************************************************************************/
33
/*                                                                        */
34
/*  FUNCTION                                               RELEASE        */
35
/*                                                                        */
36
/*    _ux_host_class_storage_media_capacity_get           PORTABLE C      */
37
/*                                                           6.1.10       */
38
/*  AUTHOR                                                                */
39
/*                                                                        */
40
/*    Chaoqiong Xiao, Microsoft Corporation                               */
41
/*                                                                        */
42
/*  DESCRIPTION                                                           */
43
/*                                                                        */
44
/*    This function will send a READ_CAPACITY command to the storage      */
45
/*    device.                                                             */
46
/*                                                                        */
47
/*  INPUT                                                                 */
48
/*                                                                        */
49
/*    storage                               Pointer to storage class      */
50
/*                                                                        */
51
/*  OUTPUT                                                                */
52
/*                                                                        */
53
/*    Completion Status                                                   */
54
/*                                                                        */
55
/*  CALLS                                                                 */
56
/*                                                                        */
57
/*    _ux_host_class_storage_cbw_initialize Initialize CBW                */
58
/*    _ux_host_class_storage_transport      Send command                  */
59
/*    _ux_host_class_storage_media_format_capacity_get                    */
60
/*                                          Get format capacity           */
61
/*    _ux_utility_memory_allocate           Allocate memory block         */
62
/*    _ux_utility_memory_free               Release memory block          */
63
/*    _ux_utility_long_get_big_endian       Get 32-bit big endian         */
64
/*                                                                        */
65
/*  CALLED BY                                                             */
66
/*                                                                        */
67
/*    Storage Class                                                       */
68
/*                                                                        */
69
/*  RELEASE HISTORY                                                       */
70
/*                                                                        */
71
/*    DATE              NAME                      DESCRIPTION             */
72
/*                                                                        */
73
/*  05-19-2020     Chaoqiong Xiao           Initial Version 6.0           */
74
/*  09-30-2020     Chaoqiong Xiao           Modified comment(s),          */
75
/*                                            added option to disable FX  */
76
/*                                            media integration,          */
77
/*                                            resulting in version 6.1    */
78
/*  01-31-2022     Chaoqiong Xiao           Modified comment(s),          */
79
/*                                            added standalone support,   */
80
/*                                            resulting in version 6.1.10 */
81
/*                                                                        */
82
/**************************************************************************/
83
179
UINT  _ux_host_class_storage_media_capacity_get(UX_HOST_CLASS_STORAGE *storage)
84
{
85
86
UINT            status;
87
UCHAR           *cbw;
88
UCHAR           *capacity_response;
89
UINT            command_length;
90
#if !defined(UX_HOST_STANDALONE)
91
ULONG           command_retry;
92
#endif
93
94
    /* If trace is enabled, insert this event into the trace buffer.  */
95
    UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_STORAGE_MEDIA_CAPACITY_GET, storage, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0)
96
97
#if !defined(UX_HOST_STANDALONE)
98
99
    /* Set the default to either 512 or 2048 bytes.  */
100
179
    switch (storage -> ux_host_class_storage_media_type)
101
    {
102
103
173
    case UX_HOST_CLASS_STORAGE_MEDIA_FAT_DISK:
104
    case UX_HOST_CLASS_STORAGE_MEDIA_IOMEGA_CLICK:
105
106
173
        storage -> ux_host_class_storage_sector_size =  UX_HOST_CLASS_STORAGE_SECTOR_SIZE_FAT;
107
173
        break;
108
109
3
    case UX_HOST_CLASS_STORAGE_MEDIA_CDROM:
110
    case UX_HOST_CLASS_STORAGE_MEDIA_OPTICAL_DISK:
111
112
3
        storage -> ux_host_class_storage_sector_size =  UX_HOST_CLASS_STORAGE_SECTOR_SIZE_OTHER;
113
3
        break;
114
115
3
    default:
116
117
        /* Unsupported device.  */
118
3
        return(UX_HOST_CLASS_MEDIA_NOT_SUPPORTED);
119
    }
120
121
    /* First, we test if the device is ready.  Then try to read its capacity.
122
       On floppies, this operation tends to fail a few times. So we try harder.  */
123
189
    for (command_retry = 0; command_retry < UX_HOST_CLASS_STORAGE_REQUEST_SENSE_RETRY; command_retry++)
124
    {
125
126
        /* Some devices require we do this.  */
127
188
        status =  _ux_host_class_storage_media_format_capacity_get(storage);
128
188
        if (status != UX_SUCCESS)
129
2
            return(status);
130
#endif
131
132
        /* Use a pointer for the cbw, easier to manipulate.  */
133
186
        cbw =  (UCHAR *) storage -> ux_host_class_storage_cbw;
134
135
        /* Get the READ_CAPACITY command Length.  */
136
#ifdef UX_HOST_CLASS_STORAGE_INCLUDE_LEGACY_PROTOCOL_SUPPORT
137
        if (storage -> ux_host_class_storage_interface -> ux_interface_descriptor.bInterfaceSubClass == UX_HOST_CLASS_STORAGE_SUBCLASS_UFI)
138
            command_length =  UX_HOST_CLASS_STORAGE_READ_CAPACITY_COMMAND_LENGTH_UFI;
139
        else
140
            command_length =  UX_HOST_CLASS_STORAGE_READ_CAPACITY_COMMAND_LENGTH_SBC;
141
#else
142
186
        command_length =  UX_HOST_CLASS_STORAGE_READ_CAPACITY_COMMAND_LENGTH_SBC;
143
#endif
144
145
        /* Initialize the CBW for this command.  */
146
186
        _ux_host_class_storage_cbw_initialize(storage, UX_HOST_CLASS_STORAGE_DATA_IN, UX_HOST_CLASS_STORAGE_READ_CAPACITY_RESPONSE_LENGTH, command_length);
147
148
        /* Prepare the READ_CAPACITY command block.  */
149
186
        *(cbw + UX_HOST_CLASS_STORAGE_CBW_CB + UX_HOST_CLASS_STORAGE_READ_CAPACITY_OPERATION) =  UX_HOST_CLASS_STORAGE_SCSI_READ_CAPACITY;
150
151
        /* Obtain a block of memory for the answer.  */
152
186
        capacity_response =  _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, UX_HOST_CLASS_STORAGE_READ_CAPACITY_RESPONSE_LENGTH);
153
186
        if (capacity_response == UX_NULL)
154
2
            return(UX_MEMORY_INSUFFICIENT);
155
156
#if defined(UX_HOST_STANDALONE)
157
158
        /* Initialize state for transport.  */
159
        UX_HOST_CLASS_STORAGE_TRANS_STATE_RESET(storage);
160
        storage -> ux_host_class_storage_state_state = UX_HOST_CLASS_STORAGE_STATE_TRANSPORT;
161
        storage -> ux_host_class_storage_state_next = UX_HOST_CLASS_STORAGE_STATE_CAP_SAVE;
162
        storage -> ux_host_class_storage_trans_data = capacity_response;
163
        status = UX_SUCCESS;
164
        return(status);
165
#else
166
167
        /* Send the command to transport layer.  */
168
184
        status =  _ux_host_class_storage_transport(storage, capacity_response);
169
170
        /* Check for error during transfer.  */
171
184
        if (status != UX_SUCCESS)
172
        {
173
174
            /* Free the memory resource used for the command response.  */
175
1
            _ux_utility_memory_free(capacity_response);
176
177
            /* We return a sad status.  */
178
1
            return(status);
179
        }
180
181
        /* Check the sense code */
182
183
        if (storage -> ux_host_class_storage_sense_code == UX_SUCCESS)
183
        {
184
185
#if defined(UX_HOST_CLASS_STORAGE_NO_FILEX)
186
            /* Save the number of sectors.  */
187
            storage -> ux_host_class_storage_last_sector_number = _ux_utility_long_get_big_endian(capacity_response + UX_HOST_CLASS_STORAGE_READ_CAPACITY_DATA_LBA);
188
#endif
189
190
            /* The data is valid, save the sector size.  */
191
170
            storage -> ux_host_class_storage_sector_size =  _ux_utility_long_get_big_endian(capacity_response + UX_HOST_CLASS_STORAGE_READ_CAPACITY_DATA_SECTOR_SIZE);
192
193
            /* Free the memory resource used for the command response.  */
194
170
            _ux_utility_memory_free(capacity_response);
195
196
            /* We return a happy status.  */
197
170
            return(UX_SUCCESS);
198
        }
199
200
        /* Free the memory resource used for the command response.  */
201
13
        _ux_utility_memory_free(capacity_response);
202
    }
203
204
    /* We get here when we could not retrieve the sector size through the READ_CAPACITY command.
205
       It's OK, we still calculated the default based on the device type.  */
206
1
    return(UX_SUCCESS);
207
#endif
208
}