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 /**************************************************************************/ 24 /* */ 25 /* COMPONENT DEFINITION RELEASE */ 26 /* */ 27 /* ux_host_class_storage.h PORTABLE C */ 28 /* 6.3.0 */ 29 /* AUTHOR */ 30 /* */ 31 /* Chaoqiong Xiao, Microsoft Corporation */ 32 /* */ 33 /* DESCRIPTION */ 34 /* */ 35 /* This file contains all the header and extern functions used by the */ 36 /* USBX storage class. */ 37 /* */ 38 /* RELEASE HISTORY */ 39 /* */ 40 /* DATE NAME DESCRIPTION */ 41 /* */ 42 /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ 43 /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */ 44 /* added option to disable FX */ 45 /* media integration, used UX_ */ 46 /* things instead of FX_ */ 47 /* things directly, used host */ 48 /* class extension pointer for */ 49 /* class specific structured */ 50 /* data, used UX prefix to */ 51 /* refer to TX symbols instead */ 52 /* of using them directly, */ 53 /* resulting in version 6.1 */ 54 /* 11-09-2020 Chaoqiong Xiao Modified comment(s), */ 55 /* added exFAT type define, */ 56 /* resulting in version 6.1.2 */ 57 /* 12-31-2020 Chaoqiong Xiao Modified comment(s), */ 58 /* resulting in version 6.1.3 */ 59 /* 08-02-2021 Chaoqiong Xiao Modified comment(s), */ 60 /* added extern "C" keyword */ 61 /* for compatibility with C++, */ 62 /* resulting in version 6.1.8 */ 63 /* 01-31-2022 Chaoqiong Xiao Modified comment(s), */ 64 /* added standalone support, */ 65 /* resulting in version 6.1.10 */ 66 /* 10-31-2023 Chaoqiong Xiao Modified comment(s), */ 67 /* added error checks support, */ 68 /* resulting in version 6.3.0 */ 69 /* */ 70 /**************************************************************************/ 71 72 #ifndef UX_HOST_CLASS_STORAGE_H 73 #define UX_HOST_CLASS_STORAGE_H 74 75 /* Determine if a C++ compiler is being used. If so, ensure that standard 76 C is used to process the API information. */ 77 78 #ifdef __cplusplus 79 80 /* Yes, C++ compiler is present. Use standard C. */ 81 extern "C" { 82 83 #endif 84 85 86 /* Internal option: enable the basic USBX error checking. This define is typically used 87 while debugging application. */ 88 #if defined(UX_ENABLE_ERROR_CHECKING) && !defined(UX_HOST_CLASS_STORAGE_ENABLE_ERROR_CHECKING) 89 #define UX_HOST_CLASS_STORAGE_ENABLE_ERROR_CHECKING 90 #endif 91 92 93 #if !defined(UX_HOST_CLASS_STORAGE_NO_FILEX) && !defined(UX_HOST_STANDALONE) 94 /* Include the FileX API. */ 95 #include "fx_api.h" 96 97 /* Refine media stubs. */ 98 99 #ifndef UX_MEDIA 100 #define UX_MEDIA FX_MEDIA 101 #endif 102 103 #ifndef ux_media_id_get 104 #define ux_media_id_get(m) ((m)->fx_media_id) 105 #endif 106 107 #ifndef ux_media_id_set 108 #define ux_media_id_set(m,id) ((m)->fx_media_id=(id)) 109 #endif 110 111 #ifndef ux_media_driver_info_get 112 #define ux_media_driver_info_get(m) ((m)->fx_media_driver_info) 113 #endif 114 115 #ifndef ux_media_driver_info_set 116 #define ux_media_driver_info_set(m,i) ((m)->fx_media_driver_info=(VOID*)(i)) 117 #endif 118 119 #ifndef ux_media_reserved_for_user_get 120 #define ux_media_reserved_for_user_get(m) ((m)->fx_media_reserved_for_user) 121 #endif 122 123 #ifndef ux_media_reserved_for_user_set 124 #define ux_media_reserved_for_user_set(m,u) ((m)->fx_media_reserved_for_user=(ALIGN_TYPE)(u)) 125 #endif 126 127 #ifndef ux_media_open 128 #define ux_media_open fx_media_open 129 #endif 130 131 #ifndef ux_media_close 132 #define ux_media_close fx_media_close 133 #endif 134 #endif 135 136 /* Define User configurable Storage Class constants. */ 137 138 #ifndef UX_MAX_HOST_LUN 139 #define UX_MAX_HOST_LUN 1 140 #endif 141 142 #ifndef UX_HOST_CLASS_STORAGE_MAX_MEDIA 143 #define UX_HOST_CLASS_STORAGE_MAX_MEDIA 1 144 #endif 145 146 #ifndef UX_HOST_CLASS_STORAGE_MEMORY_BUFFER_SIZE 147 #define UX_HOST_CLASS_STORAGE_MEMORY_BUFFER_SIZE (1024) 148 #endif 149 150 #ifndef UX_HOST_CLASS_STORAGE_MAX_TRANSFER_SIZE 151 #define UX_HOST_CLASS_STORAGE_MAX_TRANSFER_SIZE (1024) 152 #endif 153 154 #ifndef UX_HOST_CLASS_STORAGE_THREAD_STACK_SIZE 155 #define UX_HOST_CLASS_STORAGE_THREAD_STACK_SIZE UX_THREAD_STACK_SIZE 156 #endif 157 158 #if defined(UX_HOST_STANDALONE) && !defined(UX_HOST_CLASS_STORAGE_NO_FILEX) 159 #define UX_HOST_CLASS_STORAGE_NO_FILEX 160 #endif 161 162 163 /* Define Storage Class constants. */ 164 165 #define UX_HOST_CLASS_STORAGE_DEVICE_INIT_DELAY (200) 166 #define UX_HOST_CLASS_STORAGE_THREAD_SLEEP_TIME (2000) 167 #define UX_HOST_CLASS_STORAGE_INSTANCE_SHUTDOWN_TIMER (10) 168 #define UX_HOST_CLASS_STORAGE_THREAD_PRIORITY_CLASS 20 169 #define UX_HOST_CLASS_STORAGE_TRANSFER_TIMEOUT 10000 170 #define UX_HOST_CLASS_STORAGE_CBI_STATUS_TIMEOUT 3000 171 #define UX_HOST_CLASS_STORAGE_CLASS 8 172 #define UX_HOST_CLASS_STORAGE_SUBCLASS_RBC 1 173 #define UX_HOST_CLASS_STORAGE_SUBCLASS_SFF8020 2 174 #define UX_HOST_CLASS_STORAGE_SUBCLASS_UFI 4 175 #define UX_HOST_CLASS_STORAGE_SUBCLASS_SFF8070 5 176 #define UX_HOST_CLASS_STORAGE_SUBCLASS_SCSI 6 177 178 #define UX_HOST_CLASS_STORAGE_CBW_SIZE 64 179 180 #define UX_HOST_CLASS_STORAGE_PROTOCOL_CBI 0 181 #define UX_HOST_CLASS_STORAGE_PROTOCOL_CB 1 182 #define UX_HOST_CLASS_STORAGE_PROTOCOL_BO 0x50 183 184 #define UX_HOST_CLASS_STORAGE_DATA_OUT 0 185 #define UX_HOST_CLASS_STORAGE_DATA_IN 0x80 186 187 #define UX_HOST_CLASS_STORAGE_CSW_PASSED 0 188 #define UX_HOST_CLASS_STORAGE_CSW_FAILED 1 189 #define UX_HOST_CLASS_STORAGE_CSW_PHASE_ERROR 2 190 191 #define UX_HOST_CLASS_STORAGE_CBW_SIGNATURE_MASK 0x43425355 192 #define UX_HOST_CLASS_STORAGE_CBW_TAG_MASK 0x55534243 193 194 #define UX_HOST_CLASS_STORAGE_MEDIA_NAME "usb disk" 195 196 #define UX_HOST_CLASS_STORAGE_MEDIA_REMOVABLE 0x80 197 #define UX_HOST_CLASS_STORAGE_MEDIA_UNKNOWN 0 198 #define UX_HOST_CLASS_STORAGE_MEDIA_KNOWN 1 199 200 #define UX_HOST_CLASS_STORAGE_MEDIA_FAT_DISK 0 201 #define UX_HOST_CLASS_STORAGE_MEDIA_CDROM 5 202 #define UX_HOST_CLASS_STORAGE_MEDIA_OPTICAL_DISK 7 203 #define UX_HOST_CLASS_STORAGE_MEDIA_IOMEGA_CLICK 0x55 204 205 #define UX_HOST_CLASS_STORAGE_RESET 0xff 206 #define UX_HOST_CLASS_STORAGE_GET_MAX_LUN 0xfe 207 208 #define UX_HOST_CLASS_STORAGE_TRANSPORT_ERROR 1 209 #define UX_HOST_CLASS_STORAGE_COMMAND_ERROR 2 210 #define UX_HOST_CLASS_STORAGE_SENSE_ERROR 3 211 212 #define UX_HOST_CLASS_STORAGE_SECTOR_SIZE_FAT 512 213 #define UX_HOST_CLASS_STORAGE_SECTOR_SIZE_OTHER 2048 214 215 #define UX_HOST_CLASS_STORAGE_REQUEST_SENSE_RETRY 10 216 217 #define UX_HOST_CLASS_STORAGE_START_MEDIA 1 218 #define UX_HOST_CLASS_STORAGE_STOP_MEDIA 0 219 220 221 #define UX_HOST_CLASS_STORAGE_MEDIA_UNMOUNTED 0 222 #define UX_HOST_CLASS_STORAGE_MEDIA_MOUNTED 1 223 224 /* Define Storage Class SCSI command constants. */ 225 226 #define UX_HOST_CLASS_STORAGE_SCSI_TEST_READY 0x00 227 #define UX_HOST_CLASS_STORAGE_SCSI_REQUEST_SENSE 0x03 228 #define UX_HOST_CLASS_STORAGE_SCSI_FORMAT 0x04 229 #define UX_HOST_CLASS_STORAGE_SCSI_INQUIRY 0x12 230 #define UX_HOST_CLASS_STORAGE_SCSI_MODE_SENSE_SHORT 0x1a 231 #define UX_HOST_CLASS_STORAGE_SCSI_START_STOP 0x1b 232 #define UX_HOST_CLASS_STORAGE_SCSI_READ_FORMAT_CAPACITY 0x23 233 #define UX_HOST_CLASS_STORAGE_SCSI_READ_CAPACITY 0x25 234 #define UX_HOST_CLASS_STORAGE_SCSI_READ16 0x28 235 #define UX_HOST_CLASS_STORAGE_SCSI_WRITE16 0x2a 236 #define UX_HOST_CLASS_STORAGE_SCSI_VERIFY 0x2f 237 #define UX_HOST_CLASS_STORAGE_SCSI_MODE_SELECT 0x55 238 #define UX_HOST_CLASS_STORAGE_SCSI_MODE_SENSE 0x5a 239 #define UX_HOST_CLASS_STORAGE_SCSI_READ32 0xa8 240 #define UX_HOST_CLASS_STORAGE_SCSI_WRITE32 0xaa 241 242 243 /* Define Storage Class SCSI command block wrapper constants. */ 244 245 #define UX_HOST_CLASS_STORAGE_CBW_SIGNATURE 0 246 #define UX_HOST_CLASS_STORAGE_CBW_TAG 4 247 #define UX_HOST_CLASS_STORAGE_CBW_DATA_LENGTH 8 248 #define UX_HOST_CLASS_STORAGE_CBW_FLAGS 12 249 #define UX_HOST_CLASS_STORAGE_CBW_LUN 13 250 #define UX_HOST_CLASS_STORAGE_CBW_CB_LENGTH 14 251 #define UX_HOST_CLASS_STORAGE_CBW_CB 15 252 253 254 /* Define Storage Class SCSI response status wrapper constants. */ 255 256 #define UX_HOST_CLASS_STORAGE_CSW_SIGNATURE 0 257 #define UX_HOST_CLASS_STORAGE_CSW_TAG 4 258 #define UX_HOST_CLASS_STORAGE_CSW_DATA_RESIDUE 8 259 #define UX_HOST_CLASS_STORAGE_CSW_STATUS 12 260 #define UX_HOST_CLASS_STORAGE_CSW_LENGTH 13 261 262 263 /* Define Storage Class SCSI inquiry command constants. */ 264 265 #define UX_HOST_CLASS_STORAGE_INQUIRY_OPERATION 0 266 #define UX_HOST_CLASS_STORAGE_INQUIRY_LUN 1 267 #define UX_HOST_CLASS_STORAGE_INQUIRY_PAGE_CODE 2 268 #define UX_HOST_CLASS_STORAGE_INQUIRY_ALLOCATION_LENGTH 4 269 #define UX_HOST_CLASS_STORAGE_INQUIRY_COMMAND_LENGTH_UFI 12 270 #define UX_HOST_CLASS_STORAGE_INQUIRY_COMMAND_LENGTH_SBC 06 271 272 273 /* Define Storage Class SCSI inquiry response constants. */ 274 275 #define UX_HOST_CLASS_STORAGE_INQUIRY_RESPONSE_PERIPHERAL_TYPE 0 276 #define UX_HOST_CLASS_STORAGE_INQUIRY_RESPONSE_REMOVABLE_MEDIA 1 277 #define UX_HOST_CLASS_STORAGE_INQUIRY_RESPONSE_DATA_FORMAT 3 278 #define UX_HOST_CLASS_STORAGE_INQUIRY_RESPONSE_ADDITIONAL_LENGTH 4 279 #define UX_HOST_CLASS_STORAGE_INQUIRY_RESPONSE_VENDOR_INFORMATION 8 280 #define UX_HOST_CLASS_STORAGE_INQUIRY_RESPONSE_PRODUCT_ID 16 281 #define UX_HOST_CLASS_STORAGE_INQUIRY_RESPONSE_PRODUCT_REVISION 32 282 #define UX_HOST_CLASS_STORAGE_INQUIRY_RESPONSE_LENGTH 36 283 284 285 /* Define Storage Class SCSI start/stop command constants. */ 286 287 #define UX_HOST_CLASS_STORAGE_START_STOP_OPERATION 0 288 #define UX_HOST_CLASS_STORAGE_START_STOP_LBUFLAGS 1 289 #define UX_HOST_CLASS_STORAGE_START_STOP_START_BIT 4 290 #define UX_HOST_CLASS_STORAGE_START_STOP_COMMAND_LENGTH_UFI 12 291 #define UX_HOST_CLASS_STORAGE_START_STOP_COMMAND_LENGTH_SBC 12 292 293 294 /* Define Storage Class SCSI mode sense command constants. */ 295 296 #define UX_HOST_CLASS_STORAGE_MODE_SENSE_OPERATION 0 297 #define UX_HOST_CLASS_STORAGE_MODE_SENSE_LUN 1 298 #define UX_HOST_CLASS_STORAGE_MODE_SENSE_PC_PAGE_CODE 2 299 #define UX_HOST_CLASS_STORAGE_MODE_SENSE_PARAMETER_LIST_LENGTH 7 300 #define UX_HOST_CLASS_STORAGE_MODE_SENSE_COMMAND_LENGTH_UFI 12 301 #define UX_HOST_CLASS_STORAGE_MODE_SENSE_COMMAND_LENGTH_SBC 12 302 303 /* Define Storage Class SCSI mode sense command constants. */ 304 305 #define UX_HOST_CLASS_STORAGE_MODE_SENSE_RESPONSE_MODE_DATA_LENGTH 0 306 #define UX_HOST_CLASS_STORAGE_MODE_SENSE_RESPONSE_MEDIUM_TYPE_CODE 2 307 #define UX_HOST_CLASS_STORAGE_MODE_SENSE_RESPONSE_ATTRIBUTES_SHORT 2 308 #define UX_HOST_CLASS_STORAGE_MODE_SENSE_RESPONSE_ATTRIBUTES 3 309 #define UX_HOST_CLASS_STORAGE_MODE_SENSE_RESPONSE_ATTRIBUTES_WP 0x80 310 311 /* Define Storage Class SCSI request sense command constants. */ 312 313 #define UX_HOST_CLASS_STORAGE_REQUEST_SENSE_OPERATION 0 314 #define UX_HOST_CLASS_STORAGE_REQUEST_SENSE_LUN 1 315 #define UX_HOST_CLASS_STORAGE_REQUEST_SENSE_ALLOCATION_LENGTH 4 316 #define UX_HOST_CLASS_STORAGE_REQUEST_SENSE_COMMAND_LENGTH_UFI 12 317 #define UX_HOST_CLASS_STORAGE_REQUEST_SENSE_COMMAND_LENGTH_SBC 12 318 319 320 /* Define Storage Class request sense response constants. */ 321 322 #define UX_HOST_CLASS_STORAGE_REQUEST_SENSE_RESPONSE_ERROR_CODE 0 323 #define UX_HOST_CLASS_STORAGE_REQUEST_SENSE_RESPONSE_SENSE_KEY 2 324 #define UX_HOST_CLASS_STORAGE_REQUEST_SENSE_RESPONSE_INFORMATION 3 325 #define UX_HOST_CLASS_STORAGE_REQUEST_SENSE_RESPONSE_ADD_LENGTH 7 326 #define UX_HOST_CLASS_STORAGE_REQUEST_SENSE_RESPONSE_CODE 12 327 #define UX_HOST_CLASS_STORAGE_REQUEST_SENSE_RESPONSE_CODE_QUALIFIER 13 328 #define UX_HOST_CLASS_STORAGE_REQUEST_SENSE_RESPONSE_LENGTH 18 329 330 331 /* Define Storage Class read format command constants. */ 332 333 #define UX_HOST_CLASS_STORAGE_READ_FORMAT_OPERATION 0 334 #define UX_HOST_CLASS_STORAGE_READ_FORMAT_LUN 1 335 #define UX_HOST_CLASS_STORAGE_READ_FORMAT_LBA 2 336 #define UX_HOST_CLASS_STORAGE_READ_FORMAT_PARAMETER_LIST_LENGTH 7 337 #define UX_HOST_CLASS_STORAGE_READ_FORMAT_COMMAND_LENGTH_UFI 12 338 #define UX_HOST_CLASS_STORAGE_READ_FORMAT_COMMAND_LENGTH_SBC 10 339 #define UX_HOST_CLASS_STORAGE_READ_FORMAT_RESPONSE_LENGTH 0xFC 340 341 /* Define Storage Class read capacity command constants. */ 342 343 #define UX_HOST_CLASS_STORAGE_READ_CAPACITY_OPERATION 0 344 #define UX_HOST_CLASS_STORAGE_READ_CAPACITY_LUN 1 345 #define UX_HOST_CLASS_STORAGE_READ_CAPACITY_LBA 2 346 #define UX_HOST_CLASS_STORAGE_READ_CAPACITY_COMMAND_LENGTH_UFI 12 347 #define UX_HOST_CLASS_STORAGE_READ_CAPACITY_COMMAND_LENGTH_SBC 10 348 #define UX_HOST_CLASS_STORAGE_READ_CAPACITY_RESPONSE_LENGTH 8 349 350 #define UX_HOST_CLASS_STORAGE_READ_CAPACITY_DATA_LBA 0 351 #define UX_HOST_CLASS_STORAGE_READ_CAPACITY_DATA_SECTOR_SIZE 4 352 353 354 /* Define Storage Class test unit read command constants. */ 355 356 #define UX_HOST_CLASS_STORAGE_TEST_READY_OPERATION 0 357 #define UX_HOST_CLASS_STORAGE_TEST_READY_LUN 1 358 #define UX_HOST_CLASS_STORAGE_TEST_READY_COMMAND_LENGTH_UFI 12 359 #define UX_HOST_CLASS_STORAGE_TEST_READY_COMMAND_LENGTH_SBC 6 360 361 /* Define Storage Class SCSI read command constants. */ 362 363 #define UX_HOST_CLASS_STORAGE_READ_OPERATION 0 364 #define UX_HOST_CLASS_STORAGE_READ_LUN 1 365 #define UX_HOST_CLASS_STORAGE_READ_LBA 2 366 #define UX_HOST_CLASS_STORAGE_READ_TRANSFER_LENGTH 7 367 #define UX_HOST_CLASS_STORAGE_READ_COMMAND_LENGTH_UFI 12 368 #define UX_HOST_CLASS_STORAGE_READ_COMMAND_LENGTH_SBC 10 369 370 371 /* Define Storage Class SCSI write command constants. */ 372 373 #define UX_HOST_CLASS_STORAGE_WRITE_OPERATION 0 374 #define UX_HOST_CLASS_STORAGE_WRITE_LUN 1 375 #define UX_HOST_CLASS_STORAGE_WRITE_LBA 2 376 #define UX_HOST_CLASS_STORAGE_WRITE_TRANSFER_LENGTH 7 377 #define UX_HOST_CLASS_STORAGE_WRITE_COMMAND_LENGTH_UFI 12 378 #define UX_HOST_CLASS_STORAGE_WRITE_COMMAND_LENGTH_SBC 10 379 380 381 /* Define Storage Class SCSI sense key definition constants. */ 382 383 #define UX_HOST_CLASS_STORAGE_SENSE_KEY_NO_SENSE 0x0 384 #define UX_HOST_CLASS_STORAGE_SENSE_KEY_RECOVERED_ERROR 0x1 385 #define UX_HOST_CLASS_STORAGE_SENSE_KEY_NOT_READY 0x2 386 #define UX_HOST_CLASS_STORAGE_SENSE_KEY_MEDIUM_ERROR 0x3 387 #define UX_HOST_CLASS_STORAGE_SENSE_KEY_HARDWARE_ERROR 0x4 388 #define UX_HOST_CLASS_STORAGE_SENSE_KEY_ILLEGAL_REQUEST 0x5 389 #define UX_HOST_CLASS_STORAGE_SENSE_KEY_UNIT_ATTENTION 0x6 390 #define UX_HOST_CLASS_STORAGE_SENSE_KEY_DATA_PROTECT 0x7 391 #define UX_HOST_CLASS_STORAGE_SENSE_KEY_BLANK_CHECK 0x8 392 #define UX_HOST_CLASS_STORAGE_SENSE_KEY_ABORTED_COMMAND 0x0b 393 #define UX_HOST_CLASS_STORAGE_SENSE_KEY_VOLUME_OVERFLOW 0x0d 394 #define UX_HOST_CLASS_STORAGE_SENSE_KEY_MISCOMPARE 0x0e 395 396 #define UX_HOST_CLASS_STORAGE_SENSE_CODE_NOT_READY 0x04 397 #define UX_HOST_CLASS_STORAGE_SENSE_CODE_WRITE_PROTECTED 0x27 398 #define UX_HOST_CLASS_STORAGE_SENSE_CODE_NOT_READY_TO_READY 0x28 399 #define UX_HOST_CLASS_STORAGE_SENSE_CODE_NOT_PRESENT 0x3A 400 401 /* Convertion between sense status and sense key, ASC, ASCQ. */ 402 403 #define UX_HOST_CLASS_STORAGE_SENSE_STATUS(key,ascode,ascqualifier) (((key) << 16) | ((ascode) << 8) | (ascqualifier)) 404 #define UX_HOST_CLASS_STORAGE_SENSE_QUALIFIER(status) ((status) & 0xFF) 405 #define UX_HOST_CLASS_STORAGE_SENSE_CODE(status) (((status) >> 8) & 0xFF) 406 #define UX_HOST_CLASS_STORAGE_SENSE_KEY(status) (((status) >> 16) & 0xFF) 407 #define UX_HOST_CLASS_STORAGE_SENSE_ASCQ(status) UX_HOST_CLASS_STORAGE_SENSE_QUALIFIER(status) 408 #define UX_HOST_CLASS_STORAGE_SENSE_ASC(status) UX_HOST_CLASS_STORAGE_SENSE_CODE(status) 409 410 411 /* Define Mode Sense page codes. */ 412 #define UX_HOST_CLASS_STORAGE_MODE_SENSE_RWER_PAGE 0x01 413 #define UX_HOST_CLASS_STORAGE_MODE_SENSE_FD_PAGE 0x05 414 #define UX_HOST_CLASS_STORAGE_MODE_SENSE_RBAC_PAGE 0x1B 415 #define UX_HOST_CLASS_STORAGE_MODE_SENSE_TP_PAGE 0x1C 416 #define UX_HOST_CLASS_STORAGE_MODE_SENSE_ALL_PAGE 0x3F 417 418 /* Define Mode Sense page codes response length . */ 419 #define UX_HOST_CLASS_STORAGE_MODE_SENSE_HEADER_PAGE_LENGTH 0x08 420 #define UX_HOST_CLASS_STORAGE_MODE_SENSE_RWER_PAGE_LENGTH 0x0c 421 #define UX_HOST_CLASS_STORAGE_MODE_SENSE_FD_PAGE_LENGTH 0x20 422 #define UX_HOST_CLASS_STORAGE_MODE_SENSE_RBAC_PAGE_LENGTH 0x0c 423 #define UX_HOST_CLASS_STORAGE_MODE_SENSE_TP_PAGE_LENGTH 0x08 424 #define UX_HOST_CLASS_STORAGE_MODE_SENSE_ALL_PAGE_LENGTH 0xC0 425 426 /* Define Storage Class useful error sense key/code constant. */ 427 428 #define UX_HOST_CLASS_STORAGE_ERROR_MEDIA_NOT_READ 0x023A00 429 430 431 /* Define Storage Class MS-DOS partition entry constants. */ 432 433 #define UX_HOST_CLASS_STORAGE_PARTITION_SIGNATURE 0xaa55 434 #define UX_HOST_CLASS_STORAGE_PARTITION_TABLE_START 446 435 436 #define UX_HOST_CLASS_STORAGE_PARTITION_BOOT_FLAG 0 437 #define UX_HOST_CLASS_STORAGE_PARTITION_START_HEAD 1 438 #define UX_HOST_CLASS_STORAGE_PARTITION_START_SECTOR 2 439 #define UX_HOST_CLASS_STORAGE_PARTITION_START_TRACK 3 440 #define UX_HOST_CLASS_STORAGE_PARTITION_TYPE 4 441 #define UX_HOST_CLASS_STORAGE_PARTITION_END_HEAD 5 442 #define UX_HOST_CLASS_STORAGE_PARTITION_END_SECTOR 6 443 #define UX_HOST_CLASS_STORAGE_PARTITION_END_TRACK 7 444 #define UX_HOST_CLASS_STORAGE_PARTITION_SECTORS_BEFORE 8 445 #define UX_HOST_CLASS_STORAGE_PARTITION_NUMBER_SECTORS 12 446 #define UX_HOST_CLASS_STORAGE_PARTITION_TABLE_SIZE 16 447 448 #define UX_HOST_CLASS_STORAGE_PARTITION_FAT_12 1 449 #define UX_HOST_CLASS_STORAGE_PARTITION_FAT_16 4 450 #define UX_HOST_CLASS_STORAGE_PARTITION_EXTENDED 5 451 #define UX_HOST_CLASS_STORAGE_PARTITION_FAT_16L 6 452 #define UX_HOST_CLASS_STORAGE_PARTITION_EXFAT 7 453 #define UX_HOST_CLASS_STORAGE_PARTITION_FAT_32_1 0x0b 454 #define UX_HOST_CLASS_STORAGE_PARTITION_FAT_32_2 0x0c 455 #define UX_HOST_CLASS_STORAGE_PARTITION_FAT_16_LBA_MAPPED 0x0e 456 #define UX_HOST_CLASS_STORAGE_PARTITION_EXTENDED_LBA_MAPPED 0x0f 457 458 /* Define Storage Class instance structure. */ 459 460 #define UX_HOST_CLASS_STORAGE_CBW_LENGTH 31 461 #define UX_HOST_CLASS_STORAGE_CSW_LENGTH 13 462 #define UX_HOST_CLASS_STORAGE_CBW_LENGTH_ALIGNED 32 463 #define UX_HOST_CLASS_STORAGE_CSW_LENGTH_ALIGNED 16 464 465 466 typedef struct UX_HOST_CLASS_STORAGE_STRUCT 467 { 468 469 struct UX_HOST_CLASS_STORAGE_STRUCT 470 *ux_host_class_storage_next_instance; 471 UX_HOST_CLASS *ux_host_class_storage_class; 472 UX_DEVICE *ux_host_class_storage_device; 473 UX_INTERFACE *ux_host_class_storage_interface; 474 UX_ENDPOINT *ux_host_class_storage_bulk_out_endpoint; 475 UX_ENDPOINT *ux_host_class_storage_bulk_in_endpoint; 476 UX_ENDPOINT *ux_host_class_storage_interrupt_endpoint; 477 UCHAR ux_host_class_storage_cbw[UX_HOST_CLASS_STORAGE_CBW_LENGTH_ALIGNED]; 478 UCHAR ux_host_class_storage_saved_cbw[UX_HOST_CLASS_STORAGE_CBW_LENGTH_ALIGNED]; 479 UCHAR ux_host_class_storage_csw[UX_HOST_CLASS_STORAGE_CSW_LENGTH_ALIGNED]; 480 UINT ux_host_class_storage_state; 481 UINT ux_host_class_storage_media_type; 482 UINT ux_host_class_storage_lun_removable_media_flags[UX_MAX_HOST_LUN]; 483 UINT ux_host_class_storage_write_protected_media; 484 UINT ux_host_class_storage_max_lun; 485 UINT ux_host_class_storage_lun; 486 UINT ux_host_class_storage_lun_types[UX_MAX_HOST_LUN]; 487 #if defined(UX_HOST_CLASS_STORAGE_NO_FILEX) 488 ULONG ux_host_class_storage_last_sector_number; 489 #endif 490 ULONG ux_host_class_storage_sector_size; 491 ULONG ux_host_class_storage_data_phase_length; 492 ULONG ux_host_class_storage_sense_code; 493 UCHAR *ux_host_class_storage_memory; 494 #if !defined(UX_HOST_STANDALONE) 495 UINT (*ux_host_class_storage_transport) (struct UX_HOST_CLASS_STORAGE_STRUCT *storage, UCHAR * data_pointer); 496 UX_SEMAPHORE ux_host_class_storage_semaphore; 497 #else 498 ULONG ux_host_class_storage_flags; 499 UINT ux_host_class_storage_status; 500 UCHAR *ux_host_class_storage_sense_memory; 501 502 /* State info for transport state machine. */ 503 UX_TRANSFER *ux_host_class_storage_trans; 504 UCHAR *ux_host_class_storage_trans_data; 505 UCHAR *ux_host_class_storage_trans_data_bak; 506 UCHAR ux_host_class_storage_trans_state; 507 UCHAR ux_host_class_storage_trans_stage; 508 UCHAR ux_host_class_storage_trans_retry; 509 UCHAR ux_host_class_storage_trans_status; 510 511 /* State info for media main state machine. */ 512 ULONG ux_host_class_storage_delay_start; 513 ULONG ux_host_class_storage_delay_ms; 514 UCHAR ux_host_class_storage_state_state; 515 UCHAR ux_host_class_storage_state_next; 516 UCHAR ux_host_class_storage_check_lun; 517 UCHAR ux_host_class_storage_op_state; 518 UCHAR ux_host_class_storage_dbg_state; 519 UCHAR ux_host_class_storage_dbg_rw_state; 520 UCHAR ux_host_class_storage_dbg_trans_state; 521 UCHAR ux_host_class_storage_dbg_trans_stage; 522 ULONG ux_host_class_storage_dbg_state_count; 523 ULONG ux_host_class_storage_dbg_rw_state_count; 524 ULONG ux_host_class_storage_dbg_trans_state_count; 525 526 #endif 527 } UX_HOST_CLASS_STORAGE; 528 529 #define UX_HOST_CLASS_STORAGE_FLAG_PROTECT (1ul << 0) 530 #define UX_HOST_CLASS_STORAGE_FLAG_LOCK (1ul << 1) 531 #define UX_HOST_CLASS_STORAGE_FLAG_CHECK_CURRENT (1ul << 2) 532 533 /* Read/write states. */ 534 535 #define UX_HOST_CLASS_STORAGE_RW_STATE_RESET(s) ((s) -> ux_host_class_storage_op_state = UX_STATE_RESET) 536 #define UX_HOST_CLASS_STORAGE_RW_STATE_IS_IDLE(s) ((s) -> ux_host_class_storage_op_state == UX_STATE_IDLE) 537 #define UX_HOST_CLASS_STORAGE_RW_STATE_IS_RESET(s) ((s) -> ux_host_class_storage_op_state == UX_STATE_RESET) 538 #define UX_HOST_CLASS_STORAGE_RW_IS_IDLE(s) (UX_HOST_CLASS_STORAGE_RW_STATE_IS_IDLE(s) || UX_HOST_CLASS_STORAGE_RW_STATE_IS_RESET(s)) 539 540 /* Main states. */ 541 542 #define UX_HOST_CLASS_STORAGE_STATE_MAX_LUN_GET (UX_STATE_CLASS_STEP + 0) 543 #define UX_HOST_CLASS_STORAGE_STATE_MAX_LUN_SAVE (UX_STATE_CLASS_STEP + 1) 544 #define UX_HOST_CLASS_STORAGE_STATE_CHECK_START (UX_STATE_CLASS_STEP + 2) 545 #define UX_HOST_CLASS_STORAGE_STATE_LOCK_WAIT (UX_STATE_CLASS_STEP + 3) 546 #define UX_HOST_CLASS_STORAGE_STATE_TEST_READY (UX_STATE_CLASS_STEP + 4) 547 #define UX_HOST_CLASS_STORAGE_STATE_TEST_CHECK (UX_STATE_CLASS_STEP + 5) 548 #define UX_HOST_CLASS_STORAGE_STATE_INQUIRY (UX_STATE_CLASS_STEP + 6) 549 #define UX_HOST_CLASS_STORAGE_STATE_INQUIRY_SAVE (UX_STATE_CLASS_STEP + 7) 550 #define UX_HOST_CLASS_STORAGE_STATE_FORMAT_CAP_GET (UX_STATE_CLASS_STEP + 8) 551 #define UX_HOST_CLASS_STORAGE_STATE_FORMAT_CAP_SAVE (UX_STATE_CLASS_STEP + 9) 552 #define UX_HOST_CLASS_STORAGE_STATE_CAP_GET (UX_STATE_CLASS_STEP + 10) 553 #define UX_HOST_CLASS_STORAGE_STATE_CAP_SAVE (UX_STATE_CLASS_STEP + 11) 554 #define UX_HOST_CLASS_STORAGE_STATE_NEXT_LUN (UX_STATE_CLASS_STEP + 12) 555 #define UX_HOST_CLASS_STORAGE_STATE_DELAY_WAIT (UX_STATE_CLASS_STEP + 13) 556 #define UX_HOST_CLASS_STORAGE_STATE_TRANSPORT (UX_STATE_CLASS_STEP + 14) 557 #define UX_HOST_CLASS_STORAGE_STATE_TRANSFER (UX_STATE_CLASS_STEP + 15) 558 #define UX_HOST_CLASS_STORAGE_STATE_CHECK_DONE (UX_STATE_CLASS_STEP + 16) 559 560 /* Transport states. */ 561 562 #define UX_HOST_CLASS_STORAGE_TRANS_STATE_RESET(s) do { \ 563 (s) -> ux_host_class_storage_trans_state = UX_STATE_RESET; \ 564 (s) -> ux_host_class_storage_trans_data = UX_NULL; \ 565 } while(0) \ 566 567 #define UX_HOST_CLASS_STORAGE_TRANS_CBW (UX_STATE_CLASS_STEP + 0) 568 #define UX_HOST_CLASS_STORAGE_TRANS_IN_NEXT (UX_STATE_CLASS_STEP + 1) 569 #define UX_HOST_CLASS_STORAGE_TRANS_OUT_NEXT (UX_STATE_CLASS_STEP + 2) 570 #define UX_HOST_CLASS_STORAGE_TRANS_CSW (UX_STATE_CLASS_STEP + 3) 571 #define UX_HOST_CLASS_STORAGE_TRANS_REQ_SENSE (UX_STATE_CLASS_STEP + 4) 572 #define UX_HOST_CLASS_STORAGE_TRANS_WAIT (UX_STATE_CLASS_STEP + 5) 573 #define UX_HOST_CLASS_STORAGE_TRANS_STATUS (UX_STATE_CLASS_STEP + 6) 574 #define UX_HOST_CLASS_STORAGE_TRANS_MS_RESET (UX_STATE_CLASS_STEP + 7) 575 #define UX_HOST_CLASS_STORAGE_TRANS_EP_RESET (UX_STATE_CLASS_STEP + 8) 576 #define UX_HOST_CLASS_STORAGE_TRANS_RESET_NEXT (UX_STATE_CLASS_STEP + 9) 577 578 #define UX_HOST_CLASS_STORAGE_STAGE_CBW (0x00u) 579 #define UX_HOST_CLASS_STORAGE_STAGE_DATA (0x01u) 580 #define UX_HOST_CLASS_STORAGE_STAGE_CSW (0x02u) 581 #define UX_HOST_CLASS_STORAGE_STAGE_MS_RESET (0x04u) 582 #define UX_HOST_CLASS_STORAGE_STAGE_EP_RESET (0x08u) 583 584 typedef struct UX_HOST_CLASS_STORAGE_EXT_STRUCT 585 { 586 #if !defined(UX_HOST_STANDALONE) 587 UX_THREAD ux_host_class_thread; 588 CHAR ux_host_class_thread_stack[UX_HOST_CLASS_STORAGE_THREAD_STACK_SIZE]; 589 #else 590 ALIGN_TYPE reserved; 591 #endif 592 } UX_HOST_CLASS_STORAGE_EXT; 593 594 595 /* Define Host Storage Class Media structure. */ 596 597 typedef struct UX_HOST_CLASS_STORAGE_MEDIA_STRUCT 598 { 599 600 #if !defined(UX_HOST_CLASS_STORAGE_NO_FILEX) 601 UX_MEDIA ux_host_class_storage_media; 602 ULONG ux_host_class_storage_media_partition_start; 603 VOID *ux_host_class_storage_media_memory; 604 ULONG ux_host_class_storage_media_status; 605 ULONG ux_host_class_storage_media_lun; 606 ULONG ux_host_class_storage_media_sector_size; 607 #else 608 struct UX_HOST_CLASS_STORAGE_STRUCT 609 *ux_host_class_storage_media_storage; 610 ULONG ux_host_class_storage_media_number_sectors; 611 USHORT ux_host_class_storage_media_sector_size; 612 UCHAR ux_host_class_storage_media_lun; 613 UCHAR ux_host_class_storage_media_status; 614 #endif 615 616 } UX_HOST_CLASS_STORAGE_MEDIA; 617 618 619 /* Define Storage Class function prototypes. */ 620 621 UINT _ux_host_class_storage_activate(UX_HOST_CLASS_COMMAND *command); 622 VOID _ux_host_class_storage_cbw_initialize(UX_HOST_CLASS_STORAGE *storage, UINT flags, 623 ULONG data_transfer_length, UINT command_length); 624 UINT _ux_host_class_storage_configure(UX_HOST_CLASS_STORAGE *storage); 625 UINT _ux_host_class_storage_deactivate(UX_HOST_CLASS_COMMAND *command); 626 UINT _ux_host_class_storage_device_initialize(UX_HOST_CLASS_STORAGE *storage); 627 UINT _ux_host_class_storage_device_reset(UX_HOST_CLASS_STORAGE *storage); 628 UINT _ux_host_class_storage_device_support_check(UX_HOST_CLASS_STORAGE *storage); 629 630 #if !defined(UX_HOST_CLASS_STORAGE_NO_FILEX) 631 VOID _ux_host_class_storage_driver_entry(UX_MEDIA *media); 632 #endif 633 634 UINT _ux_host_class_storage_endpoints_get(UX_HOST_CLASS_STORAGE *storage); 635 UINT _ux_host_class_storage_entry(UX_HOST_CLASS_COMMAND *command); 636 UINT _ux_host_class_storage_max_lun_get(UX_HOST_CLASS_STORAGE *storage); 637 UINT _ux_host_class_storage_media_capacity_get(UX_HOST_CLASS_STORAGE *storage); 638 UINT _ux_host_class_storage_media_characteristics_get(UX_HOST_CLASS_STORAGE *storage); 639 UINT _ux_host_class_storage_media_format_capacity_get(UX_HOST_CLASS_STORAGE *storage); 640 UINT _ux_host_class_storage_media_mount(UX_HOST_CLASS_STORAGE *storage, ULONG sector); 641 UINT _ux_host_class_storage_media_open(UX_HOST_CLASS_STORAGE *storage, ULONG hidden_sectors); 642 UINT _ux_host_class_storage_media_protection_check(UX_HOST_CLASS_STORAGE *storage); 643 UINT _ux_host_class_storage_media_read(UX_HOST_CLASS_STORAGE *storage, ULONG sector_start, 644 ULONG sector_count, UCHAR *data_pointer); 645 UINT _ux_host_class_storage_media_recovery_sense_get(UX_HOST_CLASS_STORAGE *storage); 646 UINT _ux_host_class_storage_media_write(UX_HOST_CLASS_STORAGE *storage, ULONG sector_start, 647 ULONG sector_count, UCHAR *data_pointer); 648 UINT _ux_host_class_storage_partition_read(UX_HOST_CLASS_STORAGE *storage, UCHAR *sector_memory, ULONG sector); 649 UINT _ux_host_class_storage_request_sense(UX_HOST_CLASS_STORAGE *storage); 650 UINT _ux_host_class_storage_sense_code_translate(UX_HOST_CLASS_STORAGE *storage, UINT status); 651 UINT _ux_host_class_storage_start_stop(UX_HOST_CLASS_STORAGE *storage, 652 ULONG start_stop_signal); 653 VOID _ux_host_class_storage_thread_entry(ULONG class_address); 654 UINT _ux_host_class_storage_transport(UX_HOST_CLASS_STORAGE *storage, UCHAR *data_pointer); 655 UINT _ux_host_class_storage_transport_bo(UX_HOST_CLASS_STORAGE *storage, UCHAR *data_pointer); 656 UINT _ux_host_class_storage_transport_cb(UX_HOST_CLASS_STORAGE *storage, UCHAR *data_pointer); 657 UINT _ux_host_class_storage_transport_cbi(UX_HOST_CLASS_STORAGE *storage, UCHAR *data_pointer); 658 UINT _ux_host_class_storage_unit_ready_test(UX_HOST_CLASS_STORAGE *storage); 659 660 UINT _ux_host_class_storage_media_get(UX_HOST_CLASS_STORAGE *storage, ULONG media_lun, UX_HOST_CLASS_STORAGE_MEDIA **storage_media); 661 UINT _ux_host_class_storage_media_lock(UX_HOST_CLASS_STORAGE_MEDIA *storage_media, ULONG wait); 662 663 #if defined(UX_HOST_STANDALONE) 664 UINT _ux_host_class_storage_lock(UX_HOST_CLASS_STORAGE *storage, ULONG wait); 665 UINT _uxe_host_class_storage_lock(UX_HOST_CLASS_STORAGE *storage, ULONG wait); 666 #define _ux_host_class_storage_unlock(s) do { (s) -> ux_host_class_storage_flags &= ~UX_HOST_CLASS_STORAGE_FLAG_LOCK; } while(0) 667 #define _uxe_host_class_storage_unlock(s) do { if((s) != UX_NULL) (s) -> ux_host_class_storage_flags &= ~UX_HOST_CLASS_STORAGE_FLAG_LOCK; } while(0) 668 #define _ux_host_class_storage_media_unlock(m) _ux_host_class_storage_unlock((m) -> ux_host_class_storage_media_storage) 669 #define _uxe_host_class_storage_media_unlock(m) do { if((m) != UX_NULL) _uxe_host_class_storage_unlock((m) -> ux_host_class_storage_media_storage); } while(0) 670 #else 671 #define _ux_host_class_storage_lock(s,w) _ux_host_semaphore_get(&(s) -> ux_host_class_storage_semaphore, (w)) 672 #define _uxe_host_class_storage_lock(s,w) (((s) != UX_NULL) ? _ux_host_semaphore_get(&(s) -> ux_host_class_storage_semaphore, (w)) : UX_INVALID_PARAMETER) 673 #define _ux_host_class_storage_unlock(s) _ux_host_semaphore_put(&(s) -> ux_host_class_storage_semaphore) 674 #define _uxe_host_class_storage_unlock(s) (((s) != UX_NULL) ? _ux_host_semaphore_put(&(s) -> ux_host_class_storage_semaphore) : UX_INVALID_PARAMETER) 675 #define _ux_host_class_storage_media_unlock(m) _ux_host_class_storage_unlock((m) -> ux_host_class_storage_media_storage) 676 #define _uxe_host_class_storage_media_unlock(m) (((m) != UX_NULL) ? _uxe_host_class_storage_unlock((m) -> ux_host_class_storage_media_storage) : UX_INVALID_PARAMETER) 677 #endif 678 #define _ux_host_class_storage_max_lun(s) ((s) -> ux_host_class_storage_max_lun) 679 #define _ux_host_class_storage_lun(s) ((s) -> ux_host_class_storage_lun) 680 #define _ux_host_class_storage_lun_select(s,l) do { (s) -> ux_host_class_storage_lun = (l); } while(0) 681 #define _uxe_host_class_storage_lun_select(s,l) do { if ((s) != UX_NULL) (s) -> ux_host_class_storage_lun = (l); } while(0) 682 #define _ux_host_class_storage_sense_status(s) ((s) -> ux_host_class_storage_sense_code) 683 684 UINT _ux_host_class_storage_media_check(UX_HOST_CLASS_STORAGE *storage); 685 686 UINT _ux_host_class_storage_tasks_run(UX_HOST_CLASS *storage_class); 687 UINT _ux_host_class_storage_transport_run(UX_HOST_CLASS_STORAGE *storage); 688 UINT _ux_host_class_storage_check_run(UX_HOST_CLASS_STORAGE *storage); 689 UINT _ux_host_class_storage_read_write_run(UX_HOST_CLASS_STORAGE *storage, 690 ULONG read_write, ULONG sector_start, ULONG sector_count, UCHAR *data_pointer); 691 692 693 UINT _uxe_host_class_storage_media_read(UX_HOST_CLASS_STORAGE *storage, ULONG sector_start, 694 ULONG sector_count, UCHAR *data_pointer); 695 UINT _uxe_host_class_storage_media_write(UX_HOST_CLASS_STORAGE *storage, ULONG sector_start, 696 ULONG sector_count, UCHAR *data_pointer); 697 698 UINT _uxe_host_class_storage_media_check(UX_HOST_CLASS_STORAGE *storage); 699 700 UINT _uxe_host_class_storage_media_get(UX_HOST_CLASS_STORAGE *storage, ULONG media_lun, UX_HOST_CLASS_STORAGE_MEDIA **storage_media); 701 UINT _uxe_host_class_storage_media_lock(UX_HOST_CLASS_STORAGE_MEDIA *storage_media, ULONG wait); 702 703 704 /* Define Storage Class API prototypes. */ 705 706 #define ux_host_class_storage_entry _ux_host_class_storage_entry 707 708 #define ux_host_class_storage_sense_status _ux_host_class_storage_sense_status 709 710 #if defined(UX_HOST_CLASS_STORAGE_ENABLE_ERROR_CHECKING) 711 712 #define ux_host_class_storage_lock _uxe_host_class_storage_lock 713 #define ux_host_class_storage_unlock _uxe_host_class_storage_unlock 714 #define ux_host_class_storage_lun_select _uxe_host_class_storage_lun_select 715 716 #define ux_host_class_storage_media_read _uxe_host_class_storage_media_read 717 #define ux_host_class_storage_media_write _uxe_host_class_storage_media_write 718 719 #define ux_host_class_storage_media_get _uxe_host_class_storage_media_get 720 #define ux_host_class_storage_media_lock _uxe_host_class_storage_media_lock 721 #define ux_host_class_storage_media_unlock _uxe_host_class_storage_media_unlock 722 723 #define ux_host_class_storage_media_check _uxe_host_class_storage_media_check 724 725 726 #else 727 728 #define ux_host_class_storage_lock _ux_host_class_storage_lock 729 #define ux_host_class_storage_unlock _ux_host_class_storage_unlock 730 #define ux_host_class_storage_lun_select _ux_host_class_storage_lun_select 731 732 #define ux_host_class_storage_media_read _ux_host_class_storage_media_read 733 #define ux_host_class_storage_media_write _ux_host_class_storage_media_write 734 735 #define ux_host_class_storage_media_get _ux_host_class_storage_media_get 736 #define ux_host_class_storage_media_lock _ux_host_class_storage_media_lock 737 #define ux_host_class_storage_media_unlock _ux_host_class_storage_media_unlock 738 739 #define ux_host_class_storage_media_check _ux_host_class_storage_media_check 740 741 #endif 742 743 744 /* Determine if a C++ compiler is being used. If so, complete the standard 745 C conditional started above. */ 746 #ifdef __cplusplus 747 } 748 #endif 749 750 #endif 751