1 /* 2 * Copyright 2008-2012, Haiku Inc. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Michael Lotz <mmlr@mlotz.ch> 7 */ 8 9 10 #include "usb_disk.h" 11 12 #include <ByteOrder.h> 13 #include <Drivers.h> 14 15 #include <stdio.h> 16 #include <stdlib.h> 17 #include <string.h> 18 19 #include <fs/devfs.h> 20 21 #include "scsi_sense.h" 22 #include "usb_disk_scsi.h" 23 24 25 #define DRIVER_NAME "usb_disk" 26 #define DEVICE_NAME_BASE "disk/usb/" 27 #define DEVICE_NAME DEVICE_NAME_BASE"%" B_PRIu32 "/%d/raw" 28 29 30 //#define TRACE_USB_DISK 31 #ifdef TRACE_USB_DISK 32 #define TRACE(x...) dprintf(DRIVER_NAME ": " x) 33 #define TRACE_ALWAYS(x...) dprintf(DRIVER_NAME ": " x) 34 #else 35 #define TRACE(x...) /* nothing */ 36 #define TRACE_ALWAYS(x...) dprintf(DRIVER_NAME ": " x) 37 #endif 38 39 40 int32 api_version = B_CUR_DRIVER_API_VERSION; 41 static usb_module_info *gUSBModule = NULL; 42 static disk_device *gDeviceList = NULL; 43 static uint32 gDeviceCount = 0; 44 static uint32 gLunCount = 0; 45 static mutex gDeviceListLock; 46 static char **gDeviceNames = NULL; 47 48 static uint8 kDeviceIcon[] = { 49 0x6e, 0x63, 0x69, 0x66, 0x0a, 0x04, 0x01, 0x73, 0x05, 0x01, 0x02, 0x01, 50 0x06, 0x02, 0xb1, 0xf8, 0x5d, 0x3a, 0x2f, 0xbf, 0xbe, 0xdb, 0x67, 0xb6, 51 0x98, 0x06, 0x4b, 0x22, 0x15, 0x47, 0x13, 0x02, 0x00, 0xed, 0xed, 0xed, 52 0xff, 0xab, 0xbc, 0xc6, 0x02, 0x01, 0x06, 0x02, 0xb9, 0x82, 0x56, 0x32, 53 0x7d, 0xfb, 0xb8, 0x06, 0x39, 0xbe, 0xd9, 0xb5, 0x4b, 0x7d, 0x31, 0x4a, 54 0xa4, 0xe7, 0x00, 0xd1, 0xde, 0xe4, 0xff, 0x7a, 0x9c, 0xae, 0x02, 0x00, 55 0x16, 0x02, 0x38, 0xe9, 0xaa, 0x3b, 0x7b, 0x1d, 0xbf, 0xb0, 0xa6, 0x3d, 56 0x16, 0x76, 0x4b, 0x84, 0x81, 0x48, 0x37, 0x36, 0x00, 0x99, 0xff, 0x53, 57 0x02, 0x00, 0x16, 0x02, 0xba, 0x38, 0x9a, 0xb8, 0xef, 0x79, 0x3e, 0x34, 58 0x8b, 0xbf, 0x56, 0x52, 0x48, 0x2c, 0x61, 0x4c, 0x4e, 0xec, 0x00, 0x40, 59 0xff, 0x01, 0x05, 0xff, 0x05, 0x46, 0x02, 0x01, 0x16, 0x02, 0x35, 0xc2, 60 0x71, 0x3a, 0xf6, 0x84, 0xb9, 0xf3, 0x5b, 0x34, 0x81, 0xa0, 0x49, 0xc0, 61 0x57, 0x49, 0x6e, 0x51, 0xff, 0xf3, 0x00, 0x52, 0x02, 0x01, 0x06, 0x02, 62 0x38, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x80, 0x00, 63 0x49, 0xa0, 0x00, 0x49, 0x80, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x06, 64 0xe3, 0x06, 0x0c, 0x06, 0x09, 0xab, 0xaa, 0x03, 0x3e, 0x5e, 0x3c, 0x5f, 65 0x3e, 0x5e, 0x60, 0x4d, 0x5a, 0x4a, 0x60, 0x47, 0x56, 0x42, 0x50, 0x45, 66 0x4c, 0x43, 0x2a, 0x54, 0x36, 0x5d, 0x36, 0x5d, 0x3a, 0x60, 0x06, 0x08, 67 0xfb, 0xea, 0x27, 0x49, 0x26, 0x48, 0x27, 0x49, 0x32, 0x56, 0x37, 0x59, 68 0x37, 0x59, 0x38, 0x5a, 0x3b, 0x59, 0x3a, 0x5a, 0x3b, 0x59, 0x58, 0x3c, 69 0x52, 0x36, 0x43, 0x29, 0x27, 0x45, 0x27, 0x45, 0x26, 0x46, 0x06, 0x05, 70 0xab, 0x03, 0x27, 0x49, 0x26, 0x48, 0x27, 0x49, 0x32, 0x56, 0x52, 0x36, 71 0x43, 0x29, 0x27, 0x45, 0x27, 0x45, 0x26, 0x46, 0x0a, 0x05, 0xc2, 0x1c, 72 0xb8, 0xf9, 0x4f, 0x25, 0xc9, 0x4c, 0xb7, 0xc4, 0x5a, 0x30, 0x51, 0x39, 73 0x0a, 0x04, 0xc5, 0x50, 0xbb, 0xc0, 0xc2, 0x1c, 0xb8, 0xf9, 0x4f, 0x25, 74 0xc9, 0x4c, 0xb7, 0xc4, 0x0a, 0x04, 0x51, 0x39, 0xc5, 0x50, 0xbb, 0xc0, 75 0xc9, 0x4c, 0xb7, 0xc4, 0x5a, 0x30, 0x0a, 0x04, 0x4f, 0x2f, 0x51, 0x31, 76 0x53, 0x2f, 0x51, 0x2d, 0x06, 0x04, 0xee, 0x4f, 0x35, 0x53, 0x30, 0x51, 77 0x32, 0x55, 0x2e, 0x58, 0x2c, 0x54, 0x31, 0x56, 0x2f, 0x52, 0x33, 0x06, 78 0x04, 0xee, 0x31, 0x58, 0x40, 0x47, 0x39, 0x4e, 0x47, 0x40, 0x50, 0x38, 79 0x41, 0x48, 0x48, 0x41, 0x3a, 0x4f, 0x08, 0x02, 0x3a, 0x40, 0x3e, 0x3c, 80 0x02, 0x04, 0x3e, 0x3a, 0xbe, 0x48, 0x3a, 0xbf, 0x9f, 0x3a, 0x41, 0x3d, 81 0x41, 0xbd, 0xe2, 0x41, 0xbf, 0x39, 0x3e, 0x40, 0xbf, 0x9f, 0x40, 0xbe, 82 0x48, 0x40, 0x3b, 0x3d, 0x3b, 0xbf, 0x39, 0x3b, 0xbd, 0xe2, 0x06, 0x05, 83 0xbe, 0x02, 0x32, 0x56, 0x36, 0x5a, 0x36, 0x5a, 0x37, 0x5b, 0x3a, 0x5a, 84 0x39, 0x5b, 0x3a, 0x5a, 0x58, 0x3c, 0x52, 0x36, 0x11, 0x0a, 0x00, 0x01, 85 0x00, 0x00, 0x0a, 0x01, 0x01, 0x03, 0x12, 0x3f, 0xe9, 0x8e, 0xbb, 0x54, 86 0xe2, 0x3b, 0x54, 0xe2, 0x3f, 0xe9, 0x8e, 0xc6, 0x4d, 0xd9, 0x45, 0xc0, 87 0xc5, 0x01, 0x17, 0x84, 0x00, 0x04, 0x0a, 0x02, 0x01, 0x04, 0x02, 0x3f, 88 0xe9, 0x8e, 0xbb, 0x54, 0xe2, 0x3b, 0x54, 0xe2, 0x3f, 0xe9, 0x8e, 0xc6, 89 0x4d, 0xd9, 0x45, 0xc0, 0xc5, 0x0a, 0x03, 0x01, 0x05, 0x02, 0x3f, 0xe9, 90 0x8e, 0xbb, 0x54, 0xe2, 0x3b, 0x54, 0xe2, 0x3f, 0xe9, 0x8e, 0xc6, 0x4d, 91 0xd9, 0x45, 0xc0, 0xc5, 0x0a, 0x01, 0x01, 0x01, 0x12, 0x3f, 0xe9, 0x8e, 92 0xbb, 0x54, 0xe2, 0x3b, 0x54, 0xe2, 0x3f, 0xe9, 0x8e, 0xc6, 0xb0, 0x64, 93 0x46, 0x78, 0x3b, 0x01, 0x17, 0x84, 0x00, 0x04, 0x0a, 0x04, 0x01, 0x02, 94 0x02, 0x3f, 0xe9, 0x8e, 0xbb, 0x54, 0xe2, 0x3b, 0x54, 0xe2, 0x3f, 0xe9, 95 0x8e, 0xc6, 0xb0, 0x64, 0x46, 0x78, 0x3b, 0x0a, 0x05, 0x01, 0x0b, 0x02, 96 0x3f, 0xe9, 0x8e, 0xbb, 0x54, 0xe2, 0x3b, 0x54, 0xe2, 0x3f, 0xe9, 0x8e, 97 0xc6, 0xb0, 0x64, 0x46, 0x78, 0x3b, 0x0a, 0x01, 0x01, 0x06, 0x02, 0x3f, 98 0xe9, 0x8e, 0xbb, 0x54, 0xe2, 0x3b, 0x54, 0xe2, 0x3f, 0xe9, 0x8e, 0xc6, 99 0x5b, 0x2d, 0x45, 0x43, 0x93, 0x0a, 0x01, 0x01, 0x06, 0x02, 0x3f, 0xe9, 100 0x8e, 0xbb, 0x54, 0xe2, 0x3b, 0x54, 0xe2, 0x3f, 0xe9, 0x8e, 0xc7, 0x7d, 101 0x8b, 0x44, 0x36, 0x9a, 0x0a, 0x06, 0x02, 0x07, 0x08, 0x02, 0x3f, 0xe9, 102 0x8e, 0xbb, 0x54, 0xe2, 0x3b, 0x54, 0xe2, 0x3f, 0xe9, 0x8e, 0xc6, 0x4d, 103 0xd9, 0x45, 0xc0, 0xc5, 0x0a, 0x01, 0x01, 0x09, 0x12, 0x3f, 0x6c, 0x5c, 104 0xba, 0xea, 0x46, 0x3a, 0xea, 0x46, 0x3f, 0x6c, 0x5c, 0xc5, 0x19, 0x6c, 105 0x46, 0x6b, 0x36, 0x01, 0x17, 0x8c, 0x22, 0x04, 0x0a, 0x07, 0x01, 0x09, 106 0x12, 0x3f, 0xe9, 0x8e, 0xbb, 0x54, 0xe2, 0x3b, 0x54, 0xe2, 0x3f, 0xe9, 107 0x8e, 0xc6, 0x4d, 0xd9, 0x45, 0xc0, 0xc5, 0x01, 0x17, 0x88, 0x22, 0x04, 108 0x0a, 0x08, 0x01, 0x09, 0x12, 0x3f, 0xe9, 0x8e, 0xbb, 0x54, 0xe2, 0x3b, 109 0x54, 0xe2, 0x3f, 0xe9, 0x8e, 0xc6, 0x01, 0xed, 0x46, 0x11, 0xa8, 0x01, 110 0x17, 0x85, 0x22, 0x04, 0x0a, 0x01, 0x01, 0x0a, 0x12, 0x3f, 0xe9, 0x8e, 111 0xbb, 0x54, 0xe2, 0x3a, 0xaa, 0x52, 0x3f, 0x21, 0x43, 0xc6, 0x59, 0xd0, 112 0x46, 0xdb, 0x8c, 0x01, 0x17, 0x84, 0x00, 0x04, 0x0a, 0x06, 0x01, 0x0a, 113 0x02, 0x3f, 0xe9, 0x8e, 0xbb, 0x54, 0xe2, 0x3b, 0x54, 0xe2, 0x3f, 0xe9, 114 0x8e, 0xc6, 0x99, 0xc6, 0x45, 0x5e, 0x3a, 0x0a, 0x01, 0x01, 0x0a, 0x12, 115 0x3f, 0x21, 0x43, 0xba, 0xaa, 0x52, 0x3a, 0xaa, 0x52, 0x3f, 0x21, 0x43, 116 0xc7, 0xd2, 0xa7, 0x49, 0x5f, 0xed, 0x01, 0x17, 0x84, 0x00, 0x04, 0x0a, 117 0x09, 0x01, 0x0a, 0x02, 0x3f, 0xe9, 0x8e, 0xbb, 0x54, 0xe2, 0x3b, 0x54, 118 0xe2, 0x3f, 0xe9, 0x8e, 0xc8, 0xa5, 0xc8, 0x48, 0xeb, 0x05 119 }; 120 121 122 // 123 //#pragma mark - Forward Declarations 124 // 125 126 127 static void usb_disk_callback(void *cookie, status_t status, void *data, 128 size_t actualLength); 129 130 status_t usb_disk_mass_storage_reset(disk_device *device); 131 uint8 usb_disk_get_max_lun(disk_device *device); 132 void usb_disk_reset_recovery(disk_device *device); 133 status_t usb_disk_transfer_data(disk_device *device, bool directionIn, 134 void *data, size_t dataLength); 135 status_t usb_disk_receive_csw(disk_device *device, 136 command_status_wrapper *status); 137 status_t usb_disk_operation(device_lun *lun, uint8 operation, 138 uint8 opLength, uint32 logicalBlockAddress, 139 uint16 transferLength, void *data, size_t *dataLength, 140 bool directionIn, err_act *action = NULL); 141 142 status_t usb_disk_request_sense(device_lun *lun, err_act *action); 143 status_t usb_disk_mode_sense(device_lun *lun); 144 status_t usb_disk_test_unit_ready(device_lun *lun, err_act *action = NULL); 145 status_t usb_disk_inquiry(device_lun *lun); 146 status_t usb_disk_reset_capacity(device_lun *lun); 147 status_t usb_disk_update_capacity(device_lun *lun); 148 status_t usb_disk_synchronize(device_lun *lun, bool force); 149 150 151 // 152 //#pragma mark - Device Allocation Helper Functions 153 // 154 155 156 void 157 usb_disk_free_device_and_luns(disk_device *device) 158 { 159 mutex_lock(&device->lock); 160 mutex_destroy(&device->lock); 161 delete_sem(device->notify); 162 for (uint8 i = 0; i < device->lun_count; i++) 163 free(device->luns[i]); 164 free(device->luns); 165 free(device); 166 } 167 168 169 // 170 //#pragma mark - Bulk-only Mass Storage Functions 171 // 172 173 174 status_t 175 usb_disk_mass_storage_reset(disk_device *device) 176 { 177 return gUSBModule->send_request(device->device, USB_REQTYPE_INTERFACE_OUT 178 | USB_REQTYPE_CLASS, REQUEST_MASS_STORAGE_RESET, 0x0000, 179 device->interface, 0, NULL, NULL); 180 } 181 182 183 uint8 184 usb_disk_get_max_lun(disk_device *device) 185 { 186 uint8 result = 0; 187 size_t actualLength = 0; 188 189 // devices that do not support multiple LUNs may stall this request 190 if (gUSBModule->send_request(device->device, USB_REQTYPE_INTERFACE_IN 191 | USB_REQTYPE_CLASS, REQUEST_GET_MAX_LUN, 0x0000, device->interface, 192 1, &result, &actualLength) != B_OK || actualLength != 1) 193 return 0; 194 195 if (result > MAX_LOGICAL_UNIT_NUMBER) { 196 // invalid max lun 197 return 0; 198 } 199 200 return result; 201 } 202 203 204 void 205 usb_disk_reset_recovery(disk_device *device) 206 { 207 usb_disk_mass_storage_reset(device); 208 gUSBModule->clear_feature(device->bulk_in, USB_FEATURE_ENDPOINT_HALT); 209 gUSBModule->clear_feature(device->bulk_out, USB_FEATURE_ENDPOINT_HALT); 210 } 211 212 213 status_t 214 usb_disk_transfer_data(disk_device *device, bool directionIn, void *data, 215 size_t dataLength) 216 { 217 status_t result = gUSBModule->queue_bulk(directionIn ? device->bulk_in 218 : device->bulk_out, data, dataLength, usb_disk_callback, device); 219 if (result != B_OK) { 220 TRACE_ALWAYS("failed to queue data transfer: %s\n", strerror(result)); 221 return result; 222 } 223 224 do { 225 result = acquire_sem_etc(device->notify, 1, B_RELATIVE_TIMEOUT, 226 10 * 1000 * 1000); 227 if (result == B_TIMED_OUT) { 228 // Cancel the transfer and collect the sem that should now be 229 // released through the callback on cancel. Handling of device 230 // reset is done in usb_disk_operation() when it detects that 231 // the transfer failed. 232 gUSBModule->cancel_queued_transfers(directionIn ? device->bulk_in 233 : device->bulk_out); 234 acquire_sem_etc(device->notify, 1, B_RELATIVE_TIMEOUT, 0); 235 } 236 } while (result == B_INTERRUPTED); 237 238 if (result != B_OK) { 239 TRACE_ALWAYS("acquire_sem failed while waiting for data transfer: %s\n", 240 strerror(result)); 241 return result; 242 } 243 244 return B_OK; 245 } 246 247 248 status_t 249 usb_disk_receive_csw(disk_device *device, command_status_wrapper *status) 250 { 251 status_t result = usb_disk_transfer_data(device, true, status, 252 sizeof(command_status_wrapper)); 253 if (result != B_OK) 254 return result; 255 256 if (device->status != B_OK 257 || device->actual_length != sizeof(command_status_wrapper)) { 258 // receiving the command status wrapper failed 259 return B_ERROR; 260 } 261 262 return B_OK; 263 } 264 265 266 status_t 267 usb_disk_operation(device_lun *lun, uint8 operation, uint8 opLength, 268 uint32 logicalBlockAddress, uint16 transferLength, void *data, 269 size_t *dataLength, bool directionIn, err_act *_action) 270 { 271 TRACE("operation: lun: %u; op: %u; oplen: %u; lba: %" B_PRIu32 272 "; tlen: %u; data: %p; dlen: %p (%lu); in: %c\n", 273 lun->logical_unit_number, operation, opLength, logicalBlockAddress, 274 transferLength, data, dataLength, dataLength ? *dataLength : 0, 275 directionIn ? 'y' : 'n'); 276 277 disk_device *device = lun->device; 278 command_block_wrapper command; 279 command.signature = CBW_SIGNATURE; 280 command.tag = device->current_tag++; 281 command.data_transfer_length = (dataLength != NULL ? *dataLength : 0); 282 command.flags = (directionIn ? CBW_DATA_INPUT : CBW_DATA_OUTPUT); 283 command.lun = lun->logical_unit_number; 284 command.command_block_length 285 = device->is_atapi ? ATAPI_COMMAND_LENGTH : opLength; 286 memset(command.command_block, 0, sizeof(command.command_block)); 287 288 switch (opLength) { 289 case 6: 290 { 291 scsi_command_6 *commandBlock 292 = (scsi_command_6 *)command.command_block; 293 commandBlock->operation = operation; 294 commandBlock->lun = lun->logical_unit_number << 5; 295 commandBlock->allocation_length = (uint8)transferLength; 296 if (operation == SCSI_MODE_SENSE_6) { 297 // we hijack the lba argument to transport the desired page 298 commandBlock->reserved[1] = (uint8)logicalBlockAddress; 299 } 300 break; 301 } 302 303 case 10: 304 { 305 scsi_command_10 *commandBlock 306 = (scsi_command_10 *)command.command_block; 307 commandBlock->operation = operation; 308 commandBlock->lun_flags = lun->logical_unit_number << 5; 309 commandBlock->logical_block_address = htonl(logicalBlockAddress); 310 commandBlock->transfer_length = htons(transferLength); 311 break; 312 } 313 314 default: 315 TRACE_ALWAYS("unsupported operation length %d\n", opLength); 316 return B_BAD_VALUE; 317 } 318 319 status_t result = usb_disk_transfer_data(device, false, &command, 320 sizeof(command_block_wrapper)); 321 if (result != B_OK) 322 return result; 323 324 if (device->status != B_OK || 325 device->actual_length != sizeof(command_block_wrapper)) { 326 // sending the command block wrapper failed 327 TRACE_ALWAYS("sending the command block wrapper failed: %s\n", 328 strerror(device->status)); 329 usb_disk_reset_recovery(device); 330 return B_ERROR; 331 } 332 333 size_t transferedData = 0; 334 if (data != NULL && dataLength != NULL && *dataLength > 0) { 335 // we have data to transfer in a data stage 336 result = usb_disk_transfer_data(device, directionIn, data, 337 *dataLength); 338 if (result != B_OK) 339 return result; 340 341 transferedData = device->actual_length; 342 if (device->status != B_OK || transferedData != *dataLength) { 343 // sending or receiving of the data failed 344 if (device->status == B_DEV_STALLED) { 345 TRACE("stall while transfering data\n"); 346 gUSBModule->clear_feature(directionIn ? device->bulk_in 347 : device->bulk_out, USB_FEATURE_ENDPOINT_HALT); 348 } else { 349 TRACE_ALWAYS("sending or receiving of the data failed: %s\n", 350 strerror(device->status)); 351 usb_disk_reset_recovery(device); 352 return B_ERROR; 353 } 354 } 355 } 356 357 command_status_wrapper status; 358 result = usb_disk_receive_csw(device, &status); 359 if (result != B_OK) { 360 // in case of a stall or error clear the stall and try again 361 gUSBModule->clear_feature(device->bulk_in, USB_FEATURE_ENDPOINT_HALT); 362 result = usb_disk_receive_csw(device, &status); 363 } 364 365 if (result != B_OK) { 366 TRACE_ALWAYS("receiving the command status wrapper failed: %s\n", 367 strerror(result)); 368 usb_disk_reset_recovery(device); 369 return result; 370 } 371 372 if (status.signature != CSW_SIGNATURE || status.tag != command.tag) { 373 // the command status wrapper is not valid 374 TRACE_ALWAYS("command status wrapper is not valid: %#" B_PRIx32 "\n", 375 status.signature); 376 usb_disk_reset_recovery(device); 377 return B_ERROR; 378 } 379 380 switch (status.status) { 381 case CSW_STATUS_COMMAND_PASSED: 382 case CSW_STATUS_COMMAND_FAILED: 383 { 384 // The residue from "status.data_residue" is not maintained 385 // correctly by some devices, so calculate it instead. 386 uint32 residue = command.data_transfer_length - transferedData; 387 388 if (dataLength != NULL) { 389 *dataLength -= residue; 390 if (transferedData < *dataLength) { 391 TRACE_ALWAYS("less data transfered than indicated: %" 392 B_PRIuSIZE " vs. %" B_PRIuSIZE "\n", transferedData, 393 *dataLength); 394 *dataLength = transferedData; 395 } 396 } 397 398 if (status.status == CSW_STATUS_COMMAND_PASSED) { 399 // the operation is complete and has succeeded 400 return B_OK; 401 } else { 402 if (operation == SCSI_REQUEST_SENSE_6) 403 return B_ERROR; 404 405 // the operation is complete but has failed at the SCSI level 406 if (operation != SCSI_TEST_UNIT_READY_6) { 407 TRACE_ALWAYS("operation %#" B_PRIx8 408 " failed at the SCSI level\n", operation); 409 } 410 411 result = usb_disk_request_sense(lun, _action); 412 return result == B_OK ? B_ERROR : result; 413 } 414 } 415 416 case CSW_STATUS_PHASE_ERROR: 417 { 418 // a protocol or device error occured 419 TRACE_ALWAYS("phase error in operation %#" B_PRIx8 "\n", operation); 420 usb_disk_reset_recovery(device); 421 return B_ERROR; 422 } 423 424 default: 425 { 426 // command status wrapper is not meaningful 427 TRACE_ALWAYS("command status wrapper has invalid status\n"); 428 usb_disk_reset_recovery(device); 429 return B_ERROR; 430 } 431 } 432 } 433 434 435 // 436 //#pragma mark - Helper/Convenience Functions 437 // 438 439 440 status_t 441 usb_disk_request_sense(device_lun *lun, err_act *_action) 442 { 443 size_t dataLength = sizeof(scsi_request_sense_6_parameter); 444 scsi_request_sense_6_parameter parameter; 445 status_t result = usb_disk_operation(lun, SCSI_REQUEST_SENSE_6, 6, 0, 446 dataLength, ¶meter, &dataLength, true); 447 if (result != B_OK) { 448 TRACE_ALWAYS("getting request sense data failed: %s\n", 449 strerror(result)); 450 return result; 451 } 452 453 const char *label = NULL; 454 err_act action = err_act_fail; 455 status_t status = B_ERROR; 456 scsi_get_sense_asc_info((parameter.additional_sense_code << 8) 457 | parameter.additional_sense_code_qualifier, &label, &action, 458 &status); 459 460 if (parameter.sense_key > SCSI_SENSE_KEY_NOT_READY 461 && parameter.sense_key != SCSI_SENSE_KEY_UNIT_ATTENTION) { 462 TRACE_ALWAYS("request_sense: key: 0x%02x; asc: 0x%02x; ascq: " 463 "0x%02x; %s\n", parameter.sense_key, parameter.additional_sense_code, 464 parameter.additional_sense_code_qualifier, 465 label ? label : "(unknown)"); 466 } 467 468 if ((parameter.additional_sense_code == 0 469 && parameter.additional_sense_code_qualifier == 0) 470 || label == NULL) { 471 scsi_get_sense_key_info(parameter.sense_key, &label, &action, &status); 472 } 473 474 if (status == B_DEV_MEDIA_CHANGED) { 475 lun->media_changed = true; 476 lun->media_present = true; 477 } else if (parameter.sense_key == SCSI_SENSE_KEY_UNIT_ATTENTION 478 && status != B_DEV_NO_MEDIA) { 479 lun->media_present = true; 480 } else if (status == B_DEV_NOT_READY) { 481 lun->media_present = false; 482 usb_disk_reset_capacity(lun); 483 } 484 485 if (_action != NULL) 486 *_action = action; 487 488 return status; 489 } 490 491 492 status_t 493 usb_disk_mode_sense(device_lun *lun) 494 { 495 size_t dataLength = sizeof(scsi_mode_sense_6_parameter); 496 scsi_mode_sense_6_parameter parameter; 497 status_t result = usb_disk_operation(lun, SCSI_MODE_SENSE_6, 6, 498 SCSI_MODE_PAGE_DEVICE_CONFIGURATION, dataLength, ¶meter, 499 &dataLength, true); 500 if (result != B_OK) { 501 TRACE_ALWAYS("getting mode sense data failed: %s\n", strerror(result)); 502 return result; 503 } 504 505 lun->write_protected 506 = (parameter.device_specific & SCSI_DEVICE_SPECIFIC_WRITE_PROTECT) 507 != 0; 508 TRACE_ALWAYS("write protected: %s\n", lun->write_protected ? "yes" : "no"); 509 return B_OK; 510 } 511 512 513 status_t 514 usb_disk_test_unit_ready(device_lun *lun, err_act *_action) 515 { 516 // if unsupported we assume the unit is fixed and therefore always ok 517 if (!lun->device->tur_supported) 518 return B_OK; 519 520 status_t result; 521 if (lun->device->is_atapi) { 522 result = usb_disk_operation(lun, SCSI_START_STOP_UNIT_6, 6, 0, 1, 523 NULL, NULL, false, _action); 524 } else { 525 result = usb_disk_operation(lun, SCSI_TEST_UNIT_READY_6, 6, 0, 0, 526 NULL, NULL, true, _action); 527 } 528 529 if (result == B_DEV_INVALID_IOCTL) { 530 lun->device->tur_supported = false; 531 return B_OK; 532 } 533 534 return result; 535 } 536 537 538 status_t 539 usb_disk_inquiry(device_lun *lun) 540 { 541 size_t dataLength = sizeof(scsi_inquiry_6_parameter); 542 scsi_inquiry_6_parameter parameter; 543 status_t result = B_ERROR; 544 err_act action = err_act_ok; 545 for (uint32 tries = 0; tries < 3; tries++) { 546 result = usb_disk_operation(lun, SCSI_INQUIRY_6, 6, 0, dataLength, 547 ¶meter, &dataLength, true, &action); 548 if (result == B_OK || (action != err_act_retry 549 && action != err_act_many_retries)) { 550 break; 551 } 552 } 553 if (result != B_OK) { 554 TRACE_ALWAYS("getting inquiry data failed: %s\n", strerror(result)); 555 lun->device_type = B_DISK; 556 lun->removable = true; 557 return result; 558 } 559 560 TRACE("peripherial_device_type 0x%02x\n", 561 parameter.peripherial_device_type); 562 TRACE("peripherial_qualifier 0x%02x\n", 563 parameter.peripherial_qualifier); 564 TRACE("removable_medium %s\n", 565 parameter.removable_medium ? "yes" : "no"); 566 TRACE("version 0x%02x\n", parameter.version); 567 TRACE("response_data_format 0x%02x\n", parameter.response_data_format); 568 TRACE_ALWAYS("vendor_identification \"%.8s\"\n", 569 parameter.vendor_identification); 570 TRACE_ALWAYS("product_identification \"%.16s\"\n", 571 parameter.product_identification); 572 TRACE_ALWAYS("product_revision_level \"%.4s\"\n", 573 parameter.product_revision_level); 574 575 memcpy(lun->vendor_name, parameter.vendor_identification, 576 MIN(sizeof(lun->vendor_name), sizeof(parameter.vendor_identification))); 577 memcpy(lun->product_name, parameter.product_identification, 578 MIN(sizeof(lun->product_name), 579 sizeof(parameter.product_identification))); 580 memcpy(lun->product_revision, parameter.product_revision_level, 581 MIN(sizeof(lun->product_revision), 582 sizeof(parameter.product_revision_level))); 583 584 lun->device_type = parameter.peripherial_device_type; /* 1:1 mapping */ 585 lun->removable = (parameter.removable_medium == 1); 586 return B_OK; 587 } 588 589 590 status_t 591 usb_disk_reset_capacity(device_lun *lun) 592 { 593 lun->block_size = 512; 594 lun->block_count = 0; 595 return B_OK; 596 } 597 598 599 status_t 600 usb_disk_update_capacity(device_lun *lun) 601 { 602 size_t dataLength = sizeof(scsi_read_capacity_10_parameter); 603 scsi_read_capacity_10_parameter parameter; 604 status_t result = B_ERROR; 605 err_act action = err_act_ok; 606 607 // Retry reading the capacity up to three times. The first try might only 608 // yield a unit attention telling us that the device or media status 609 // changed, which is more or less expected if it is the first operation 610 // on the device or the device only clears the unit atention for capacity 611 // reads. 612 for (int32 i = 0; i < 3; i++) { 613 result = usb_disk_operation(lun, SCSI_READ_CAPACITY_10, 10, 0, 0, 614 ¶meter, &dataLength, true, &action); 615 if (result == B_OK || (action != err_act_retry 616 && action != err_act_many_retries)) { 617 break; 618 } 619 } 620 621 if (result != B_OK) { 622 TRACE_ALWAYS("failed to update capacity: %s\n", strerror(result)); 623 lun->media_present = false; 624 lun->media_changed = false; 625 usb_disk_reset_capacity(lun); 626 return result; 627 } 628 629 lun->media_present = true; 630 lun->media_changed = false; 631 lun->block_size = ntohl(parameter.logical_block_length); 632 lun->block_count = ntohl(parameter.last_logical_block_address) + 1; 633 return B_OK; 634 } 635 636 637 status_t 638 usb_disk_synchronize(device_lun *lun, bool force) 639 { 640 if (lun->device->sync_support == 0) { 641 // this device reported an illegal request when syncing or repeatedly 642 // returned an other error, it apparently does not support syncing... 643 return B_UNSUPPORTED; 644 } 645 646 if (!lun->should_sync && !force) 647 return B_OK; 648 649 status_t result = usb_disk_operation(lun, SCSI_SYNCHRONIZE_CACHE_10, 10, 650 0, 0, NULL, NULL, false); 651 652 if (result == B_OK) { 653 lun->device->sync_support = SYNC_SUPPORT_RELOAD; 654 lun->should_sync = false; 655 return B_OK; 656 } 657 658 if (result == B_DEV_INVALID_IOCTL) 659 lun->device->sync_support = 0; 660 else 661 lun->device->sync_support--; 662 663 return result; 664 } 665 666 667 // 668 //#pragma mark - Device Attach/Detach Notifications and Callback 669 // 670 671 672 static void 673 usb_disk_callback(void *cookie, status_t status, void *data, 674 size_t actualLength) 675 { 676 //TRACE("callback()\n"); 677 disk_device *device = (disk_device *)cookie; 678 device->status = status; 679 device->actual_length = actualLength; 680 release_sem(device->notify); 681 } 682 683 684 static status_t 685 usb_disk_device_added(usb_device newDevice, void **cookie) 686 { 687 TRACE("device_added(0x%08" B_PRIx32 ")\n", newDevice); 688 disk_device *device = (disk_device *)malloc(sizeof(disk_device)); 689 device->device = newDevice; 690 device->removed = false; 691 device->open_count = 0; 692 device->interface = 0xff; 693 device->current_tag = 0; 694 device->sync_support = SYNC_SUPPORT_RELOAD; 695 device->tur_supported = true; 696 device->is_atapi = false; 697 device->luns = NULL; 698 699 // scan through the interfaces to find our bulk-only data interface 700 const usb_configuration_info *configuration 701 = gUSBModule->get_configuration(newDevice); 702 if (configuration == NULL) { 703 free(device); 704 return B_ERROR; 705 } 706 707 for (size_t i = 0; i < configuration->interface_count; i++) { 708 usb_interface_info *interface = configuration->interface[i].active; 709 if (interface == NULL) 710 continue; 711 712 if (interface->descr->interface_class == 0x08 /* mass storage */ 713 && (interface->descr->interface_subclass == 0x06 /* SCSI */ 714 || interface->descr->interface_subclass == 0x02 /* ATAPI */ 715 || interface->descr->interface_subclass == 0x05 /* ATAPI */) 716 && interface->descr->interface_protocol == 0x50 /* bulk-only */) { 717 718 bool hasIn = false; 719 bool hasOut = false; 720 for (size_t j = 0; j < interface->endpoint_count; j++) { 721 usb_endpoint_info *endpoint = &interface->endpoint[j]; 722 if (endpoint == NULL 723 || endpoint->descr->attributes != USB_ENDPOINT_ATTR_BULK) 724 continue; 725 726 if (!hasIn && (endpoint->descr->endpoint_address 727 & USB_ENDPOINT_ADDR_DIR_IN) != 0) { 728 device->bulk_in = endpoint->handle; 729 hasIn = true; 730 } else if (!hasOut && (endpoint->descr->endpoint_address 731 & USB_ENDPOINT_ADDR_DIR_IN) == 0) { 732 device->bulk_out = endpoint->handle; 733 hasOut = true; 734 } 735 736 if (hasIn && hasOut) 737 break; 738 } 739 740 if (!(hasIn && hasOut)) 741 continue; 742 743 device->interface = interface->descr->interface_number; 744 device->is_atapi = interface->descr->interface_subclass != 0x06; 745 break; 746 } 747 } 748 749 if (device->interface == 0xff) { 750 TRACE_ALWAYS("no valid bulk-only interface found\n"); 751 free(device); 752 return B_ERROR; 753 } 754 755 mutex_init(&device->lock, "usb_disk device lock"); 756 757 device->notify = create_sem(0, "usb_disk callback notify"); 758 if (device->notify < B_OK) { 759 mutex_destroy(&device->lock); 760 status_t result = device->notify; 761 free(device); 762 return result; 763 } 764 765 device->lun_count = usb_disk_get_max_lun(device) + 1; 766 device->luns = (device_lun **)malloc(device->lun_count 767 * sizeof(device_lun *)); 768 for (uint8 i = 0; i < device->lun_count; i++) 769 device->luns[i] = NULL; 770 771 status_t result = B_OK; 772 773 TRACE_ALWAYS("device reports a lun count of %d\n", device->lun_count); 774 for (uint8 i = 0; i < device->lun_count; i++) { 775 // create the individual luns present on this device 776 device_lun *lun = (device_lun *)malloc(sizeof(device_lun)); 777 if (lun == NULL) { 778 result = B_NO_MEMORY; 779 break; 780 } 781 782 device->luns[i] = lun; 783 lun->device = device; 784 lun->logical_unit_number = i; 785 lun->should_sync = false; 786 lun->media_present = true; 787 lun->media_changed = true; 788 789 memset(lun->vendor_name, 0, sizeof(lun->vendor_name)); 790 memset(lun->product_name, 0, sizeof(lun->product_name)); 791 memset(lun->product_revision, 0, sizeof(lun->product_revision)); 792 793 usb_disk_reset_capacity(lun); 794 795 // initialize this lun 796 result = usb_disk_inquiry(lun); 797 err_act action = err_act_ok; 798 for (uint32 tries = 0; tries < 8; tries++) { 799 TRACE("usb lun %" B_PRIu8 " inquiry attempt %" B_PRIu32 " begin\n", 800 i, tries); 801 status_t ready = usb_disk_test_unit_ready(lun, &action); 802 if (ready == B_OK || ready == B_DEV_NO_MEDIA 803 || ready == B_DEV_MEDIA_CHANGED) { 804 if (lun->device_type == B_CD) 805 lun->write_protected = true; 806 // TODO: check for write protection; disabled since some 807 // devices lock up when getting the mode sense 808 else if (/*usb_disk_mode_sense(lun) != B_OK*/true) 809 lun->write_protected = false; 810 811 TRACE("usb lun %" B_PRIu8 " ready. write protected = %c%s\n", i, 812 lun->write_protected ? 'y' : 'n', 813 ready == B_DEV_NO_MEDIA ? " (no media inserted)" : ""); 814 815 break; 816 } 817 TRACE("usb lun %" B_PRIu8 " inquiry attempt %" B_PRIu32 " failed\n", 818 i, tries); 819 if (action != err_act_retry && action != err_act_many_retries) 820 break; 821 bigtime_t snoozeTime = 1000000 * tries; 822 TRACE("snoozing %" B_PRIu64 " microseconds for usb lun\n", 823 snoozeTime); 824 snooze(snoozeTime); 825 } 826 827 if (result != B_OK) 828 break; 829 } 830 831 if (result != B_OK) { 832 TRACE_ALWAYS("failed to initialize logical units: %s\n", 833 strerror(result)); 834 usb_disk_free_device_and_luns(device); 835 return result; 836 } 837 838 mutex_lock(&gDeviceListLock); 839 device->device_number = 0; 840 disk_device *other = gDeviceList; 841 while (other != NULL) { 842 if (other->device_number >= device->device_number) 843 device->device_number = other->device_number + 1; 844 845 other = (disk_device *)other->link; 846 } 847 848 device->link = (void *)gDeviceList; 849 gDeviceList = device; 850 gLunCount += device->lun_count; 851 for (uint8 i = 0; i < device->lun_count; i++) 852 sprintf(device->luns[i]->name, DEVICE_NAME, device->device_number, i); 853 mutex_unlock(&gDeviceListLock); 854 855 TRACE("new device: 0x%p\n", device); 856 *cookie = (void *)device; 857 return B_OK; 858 } 859 860 861 static status_t 862 usb_disk_device_removed(void *cookie) 863 { 864 TRACE("device_removed(0x%p)\n", cookie); 865 disk_device *device = (disk_device *)cookie; 866 867 mutex_lock(&gDeviceListLock); 868 if (gDeviceList == device) { 869 gDeviceList = (disk_device *)device->link; 870 } else { 871 disk_device *element = gDeviceList; 872 while (element) { 873 if (element->link == device) { 874 element->link = device->link; 875 break; 876 } 877 878 element = (disk_device *)element->link; 879 } 880 } 881 gLunCount -= device->lun_count; 882 gDeviceCount--; 883 884 device->removed = true; 885 gUSBModule->cancel_queued_transfers(device->bulk_in); 886 gUSBModule->cancel_queued_transfers(device->bulk_out); 887 if (device->open_count == 0) 888 usb_disk_free_device_and_luns(device); 889 890 mutex_unlock(&gDeviceListLock); 891 return B_OK; 892 } 893 894 895 // 896 //#pragma mark - Partial Buffer Functions 897 // 898 899 900 static bool 901 usb_disk_needs_partial_buffer(device_lun *lun, off_t position, size_t length, 902 uint32 &blockPosition, uint16 &blockCount) 903 { 904 blockPosition = (uint32)(position / lun->block_size); 905 if ((off_t)blockPosition * lun->block_size != position) 906 return true; 907 908 blockCount = (uint16)(length / lun->block_size); 909 if ((size_t)blockCount * lun->block_size != length) 910 return true; 911 912 return false; 913 } 914 915 916 static status_t 917 usb_disk_block_read(device_lun *lun, uint32 blockPosition, uint16 blockCount, 918 void *buffer, size_t *length) 919 { 920 status_t result = usb_disk_operation(lun, SCSI_READ_10, 10, blockPosition, 921 blockCount, buffer, length, true); 922 return result; 923 } 924 925 926 static status_t 927 usb_disk_block_write(device_lun *lun, uint32 blockPosition, uint16 blockCount, 928 void *buffer, size_t *length) 929 { 930 status_t result = usb_disk_operation(lun, SCSI_WRITE_10, 10, blockPosition, 931 blockCount, buffer, length, false); 932 if (result == B_OK) 933 lun->should_sync = true; 934 return result; 935 } 936 937 938 static status_t 939 usb_disk_prepare_partial_buffer(device_lun *lun, off_t position, size_t length, 940 void *&partialBuffer, void *&blockBuffer, uint32 &blockPosition, 941 uint16 &blockCount) 942 { 943 blockPosition = (uint32)(position / lun->block_size); 944 blockCount = (uint16)((uint32)((position + length + lun->block_size - 1) 945 / lun->block_size) - blockPosition); 946 size_t blockLength = blockCount * lun->block_size; 947 blockBuffer = malloc(blockLength); 948 if (blockBuffer == NULL) { 949 TRACE_ALWAYS("no memory to allocate partial buffer\n"); 950 return B_NO_MEMORY; 951 } 952 953 status_t result = usb_disk_block_read(lun, blockPosition, blockCount, 954 blockBuffer, &blockLength); 955 if (result != B_OK) { 956 TRACE_ALWAYS("block read failed when filling partial buffer: %s\n", 957 strerror(result)); 958 free(blockBuffer); 959 return result; 960 } 961 962 off_t offset = position - (off_t)blockPosition * lun->block_size; 963 partialBuffer = (uint8 *)blockBuffer + offset; 964 return B_OK; 965 } 966 967 968 // 969 //#pragma mark - Driver Hooks 970 // 971 972 973 static status_t 974 usb_disk_open(const char *name, uint32 flags, void **cookie) 975 { 976 TRACE("open(%s)\n", name); 977 if (strncmp(name, DEVICE_NAME_BASE, strlen(DEVICE_NAME_BASE)) != 0) 978 return B_NAME_NOT_FOUND; 979 980 int32 lastPart = 0; 981 size_t nameLength = strlen(name); 982 for (int32 i = nameLength - 1; i >= 0; i--) { 983 if (name[i] == '/') { 984 lastPart = i; 985 break; 986 } 987 } 988 989 char rawName[nameLength + 4]; 990 strncpy(rawName, name, lastPart + 1); 991 rawName[lastPart + 1] = 0; 992 strcat(rawName, "raw"); 993 TRACE("opening raw device %s for %s\n", rawName, name); 994 995 mutex_lock(&gDeviceListLock); 996 disk_device *device = gDeviceList; 997 while (device) { 998 for (uint8 i = 0; i < device->lun_count; i++) { 999 device_lun *lun = device->luns[i]; 1000 if (strncmp(rawName, lun->name, 32) == 0) { 1001 // found the matching device/lun 1002 if (device->removed) { 1003 mutex_unlock(&gDeviceListLock); 1004 return B_ERROR; 1005 } 1006 1007 device->open_count++; 1008 *cookie = lun; 1009 mutex_unlock(&gDeviceListLock); 1010 return B_OK; 1011 } 1012 } 1013 1014 device = (disk_device *)device->link; 1015 } 1016 1017 mutex_unlock(&gDeviceListLock); 1018 return B_NAME_NOT_FOUND; 1019 } 1020 1021 1022 static status_t 1023 usb_disk_close(void *cookie) 1024 { 1025 TRACE("close()\n"); 1026 device_lun *lun = (device_lun *)cookie; 1027 disk_device *device = lun->device; 1028 1029 mutex_lock(&device->lock); 1030 if (!device->removed) 1031 usb_disk_synchronize(lun, false); 1032 mutex_unlock(&device->lock); 1033 1034 return B_OK; 1035 } 1036 1037 1038 static status_t 1039 usb_disk_free(void *cookie) 1040 { 1041 TRACE("free()\n"); 1042 mutex_lock(&gDeviceListLock); 1043 1044 device_lun *lun = (device_lun *)cookie; 1045 disk_device *device = lun->device; 1046 device->open_count--; 1047 if (device->open_count == 0 && device->removed) { 1048 // we can simply free the device here as it has been removed from 1049 // the device list in the device removed notification hook 1050 usb_disk_free_device_and_luns(device); 1051 } 1052 1053 mutex_unlock(&gDeviceListLock); 1054 return B_OK; 1055 } 1056 1057 1058 static inline void 1059 normalize_name(char *name, size_t nameLength) 1060 { 1061 bool wasSpace = false; 1062 size_t insertIndex = 0; 1063 for (size_t i = 0; i < nameLength; i++) { 1064 bool isSpace = name[i] == ' '; 1065 if (isSpace && wasSpace) 1066 continue; 1067 1068 name[insertIndex++] = name[i]; 1069 wasSpace = isSpace; 1070 } 1071 1072 if (insertIndex > 0 && name[insertIndex - 1] == ' ') 1073 insertIndex--; 1074 1075 name[insertIndex] = 0; 1076 } 1077 1078 1079 static status_t 1080 usb_disk_ioctl(void *cookie, uint32 op, void *buffer, size_t length) 1081 { 1082 device_lun *lun = (device_lun *)cookie; 1083 disk_device *device = lun->device; 1084 mutex_lock(&device->lock); 1085 if (device->removed) { 1086 mutex_unlock(&device->lock); 1087 return B_DEV_NOT_READY; 1088 } 1089 1090 status_t result = B_DEV_INVALID_IOCTL; 1091 switch (op) { 1092 case B_GET_MEDIA_STATUS: 1093 { 1094 err_act action = err_act_ok; 1095 for (uint32 tries = 0; tries < 3; tries++) { 1096 status_t ready = usb_disk_test_unit_ready(lun, &action); 1097 if (ready == B_OK || ready == B_DEV_NO_MEDIA 1098 || (action != err_act_retry 1099 && action != err_act_many_retries)) { 1100 *(status_t *)buffer = ready; 1101 break; 1102 } 1103 snooze(500000); 1104 } 1105 TRACE("B_GET_MEDIA_STATUS: 0x%08" B_PRIx32 "\n", 1106 *(status_t *)buffer); 1107 result = B_OK; 1108 break; 1109 } 1110 1111 case B_GET_GEOMETRY: 1112 { 1113 if (lun->media_changed) { 1114 result = usb_disk_update_capacity(lun); 1115 if (result != B_OK) 1116 break; 1117 } 1118 1119 device_geometry geometry; 1120 devfs_compute_geometry_size(&geometry, lun->block_count, 1121 lun->block_size); 1122 1123 geometry.device_type = lun->device_type; 1124 geometry.removable = lun->removable; 1125 geometry.read_only = lun->write_protected; 1126 geometry.write_once = lun->device_type == B_WORM; 1127 TRACE("B_GET_GEOMETRY: %" B_PRId32 " sectors at %" B_PRId32 1128 " bytes per sector\n", geometry.cylinder_count, 1129 geometry.bytes_per_sector); 1130 result = user_memcpy(buffer, &geometry, sizeof(device_geometry)); 1131 break; 1132 } 1133 1134 case B_FLUSH_DRIVE_CACHE: 1135 TRACE("B_FLUSH_DRIVE_CACHE\n"); 1136 result = usb_disk_synchronize(lun, true); 1137 break; 1138 1139 case B_EJECT_DEVICE: 1140 result = usb_disk_operation(lun, SCSI_START_STOP_UNIT_6, 6, 0, 2, 1141 NULL, NULL, false); 1142 break; 1143 1144 case B_LOAD_MEDIA: 1145 result = usb_disk_operation(lun, SCSI_START_STOP_UNIT_6, 6, 0, 3, 1146 NULL, NULL, false); 1147 break; 1148 1149 #if HAIKU_TARGET_PLATFORM_HAIKU 1150 case B_GET_ICON: 1151 // We don't support this legacy ioctl anymore, but the two other 1152 // icon ioctls below instead. 1153 break; 1154 1155 case B_GET_ICON_NAME: 1156 result = user_strlcpy((char *)buffer, 1157 "devices/drive-removable-media-usb", B_FILE_NAME_LENGTH); 1158 break; 1159 1160 case B_GET_VECTOR_ICON: 1161 { 1162 if (length != sizeof(device_icon)) { 1163 result = B_BAD_VALUE; 1164 break; 1165 } 1166 1167 device_icon iconData; 1168 if (user_memcpy(&iconData, buffer, sizeof(device_icon)) != B_OK) { 1169 result = B_BAD_ADDRESS; 1170 break; 1171 } 1172 1173 if (iconData.icon_size >= (int32)sizeof(kDeviceIcon)) { 1174 if (user_memcpy(iconData.icon_data, kDeviceIcon, 1175 sizeof(kDeviceIcon)) != B_OK) { 1176 result = B_BAD_ADDRESS; 1177 break; 1178 } 1179 } 1180 1181 iconData.icon_size = sizeof(kDeviceIcon); 1182 result = user_memcpy(buffer, &iconData, sizeof(device_icon)); 1183 break; 1184 } 1185 1186 case B_GET_DEVICE_NAME: 1187 { 1188 size_t nameLength = sizeof(lun->vendor_name) 1189 + sizeof(lun->product_name) + sizeof(lun->product_revision) + 3; 1190 1191 char name[nameLength]; 1192 snprintf(name, nameLength, "%.8s %.16s %.4s", lun->vendor_name, 1193 lun->product_name, lun->product_revision); 1194 1195 normalize_name(name, nameLength); 1196 1197 result = user_strlcpy((char *)buffer, name, length); 1198 if (result > 0) 1199 result = B_OK; 1200 1201 TRACE_ALWAYS("got device name \"%s\": %s\n", name, 1202 strerror(result)); 1203 break; 1204 } 1205 #endif 1206 1207 default: 1208 TRACE_ALWAYS("unhandled ioctl %" B_PRId32 "\n", op); 1209 break; 1210 } 1211 1212 mutex_unlock(&device->lock); 1213 return result; 1214 } 1215 1216 1217 static status_t 1218 usb_disk_read(void *cookie, off_t position, void *buffer, size_t *length) 1219 { 1220 if (buffer == NULL || length == NULL) 1221 return B_BAD_VALUE; 1222 1223 TRACE("read(%" B_PRIdOFF ", %ld)\n", position, *length); 1224 device_lun *lun = (device_lun *)cookie; 1225 disk_device *device = lun->device; 1226 mutex_lock(&device->lock); 1227 if (device->removed) { 1228 *length = 0; 1229 mutex_unlock(&device->lock); 1230 return B_DEV_NOT_READY; 1231 } 1232 1233 status_t result = B_ERROR; 1234 uint32 blockPosition = 0; 1235 uint16 blockCount = 0; 1236 bool needsPartial = usb_disk_needs_partial_buffer(lun, position, *length, 1237 blockPosition, blockCount); 1238 if (needsPartial) { 1239 void *partialBuffer = NULL; 1240 void *blockBuffer = NULL; 1241 result = usb_disk_prepare_partial_buffer(lun, position, *length, 1242 partialBuffer, blockBuffer, blockPosition, blockCount); 1243 if (result == B_OK) { 1244 memcpy(buffer, partialBuffer, *length); 1245 free(blockBuffer); 1246 } 1247 } else { 1248 result = usb_disk_block_read(lun, blockPosition, blockCount, buffer, 1249 length); 1250 } 1251 1252 mutex_unlock(&device->lock); 1253 if (result == B_OK) { 1254 TRACE("read successful with %ld bytes\n", *length); 1255 return B_OK; 1256 } 1257 1258 *length = 0; 1259 TRACE_ALWAYS("read failed: %s\n", strerror(result)); 1260 return result; 1261 } 1262 1263 1264 static status_t 1265 usb_disk_write(void *cookie, off_t position, const void *buffer, 1266 size_t *length) 1267 { 1268 if (buffer == NULL || length == NULL) 1269 return B_BAD_VALUE; 1270 1271 TRACE("write(%" B_PRIdOFF", %ld)\n", position, *length); 1272 device_lun *lun = (device_lun *)cookie; 1273 disk_device *device = lun->device; 1274 mutex_lock(&device->lock); 1275 if (device->removed) { 1276 *length = 0; 1277 mutex_unlock(&device->lock); 1278 return B_DEV_NOT_READY; 1279 } 1280 1281 status_t result = B_ERROR; 1282 uint32 blockPosition = 0; 1283 uint16 blockCount = 0; 1284 bool needsPartial = usb_disk_needs_partial_buffer(lun, position, 1285 *length, blockPosition, blockCount); 1286 if (needsPartial) { 1287 void *partialBuffer = NULL; 1288 void *blockBuffer = NULL; 1289 result = usb_disk_prepare_partial_buffer(lun, position, *length, 1290 partialBuffer, blockBuffer, blockPosition, blockCount); 1291 if (result == B_OK) { 1292 memcpy(partialBuffer, buffer, *length); 1293 size_t blockLength = blockCount * lun->block_size; 1294 result = usb_disk_block_write(lun, blockPosition, blockCount, 1295 blockBuffer, &blockLength); 1296 free(blockBuffer); 1297 } 1298 } else { 1299 result = usb_disk_block_write(lun, blockPosition, blockCount, 1300 (void *)buffer, length); 1301 } 1302 1303 mutex_unlock(&device->lock); 1304 if (result == B_OK) { 1305 TRACE("write successful with %ld bytes\n", *length); 1306 return B_OK; 1307 } 1308 1309 *length = 0; 1310 TRACE_ALWAYS("write failed: %s\n", strerror(result)); 1311 return result; 1312 } 1313 1314 1315 // 1316 //#pragma mark - Driver Entry Points 1317 // 1318 1319 1320 status_t 1321 init_hardware() 1322 { 1323 TRACE("init_hardware()\n"); 1324 return B_OK; 1325 } 1326 1327 1328 status_t 1329 init_driver() 1330 { 1331 TRACE("init_driver()\n"); 1332 static usb_notify_hooks notifyHooks = { 1333 &usb_disk_device_added, 1334 &usb_disk_device_removed 1335 }; 1336 1337 static usb_support_descriptor supportedDevices[] = { 1338 { 0x08 /* mass storage */, 0x06 /* SCSI */, 0x50 /* bulk */, 0, 0 }, 1339 { 0x08 /* mass storage */, 0x02 /* ATAPI */, 0x50 /* bulk */, 0, 0 }, 1340 { 0x08 /* mass storage */, 0x05 /* ATAPI */, 0x50 /* bulk */, 0, 0 } 1341 }; 1342 1343 gDeviceList = NULL; 1344 gDeviceCount = 0; 1345 gLunCount = 0; 1346 mutex_init(&gDeviceListLock, "usb_disk device list lock"); 1347 1348 TRACE("trying module %s\n", B_USB_MODULE_NAME); 1349 status_t result = get_module(B_USB_MODULE_NAME, 1350 (module_info **)&gUSBModule); 1351 if (result < B_OK) { 1352 TRACE_ALWAYS("getting module failed: %s\n", strerror(result)); 1353 mutex_destroy(&gDeviceListLock); 1354 return result; 1355 } 1356 1357 gUSBModule->register_driver(DRIVER_NAME, supportedDevices, 3, NULL); 1358 gUSBModule->install_notify(DRIVER_NAME, ¬ifyHooks); 1359 return B_OK; 1360 } 1361 1362 1363 void 1364 uninit_driver() 1365 { 1366 TRACE("uninit_driver()\n"); 1367 gUSBModule->uninstall_notify(DRIVER_NAME); 1368 mutex_lock(&gDeviceListLock); 1369 1370 if (gDeviceNames) { 1371 for (int32 i = 0; gDeviceNames[i]; i++) 1372 free(gDeviceNames[i]); 1373 free(gDeviceNames); 1374 gDeviceNames = NULL; 1375 } 1376 1377 mutex_destroy(&gDeviceListLock); 1378 put_module(B_USB_MODULE_NAME); 1379 } 1380 1381 1382 const char ** 1383 publish_devices() 1384 { 1385 TRACE("publish_devices()\n"); 1386 if (gDeviceNames) { 1387 for (int32 i = 0; gDeviceNames[i]; i++) 1388 free(gDeviceNames[i]); 1389 free(gDeviceNames); 1390 gDeviceNames = NULL; 1391 } 1392 1393 gDeviceNames = (char **)malloc(sizeof(char *) * (gLunCount + 1)); 1394 if (gDeviceNames == NULL) 1395 return NULL; 1396 1397 int32 index = 0; 1398 mutex_lock(&gDeviceListLock); 1399 disk_device *device = gDeviceList; 1400 while (device) { 1401 for (uint8 i = 0; i < device->lun_count; i++) 1402 gDeviceNames[index++] = strdup(device->luns[i]->name); 1403 1404 device = (disk_device *)device->link; 1405 } 1406 1407 gDeviceNames[index++] = NULL; 1408 mutex_unlock(&gDeviceListLock); 1409 return (const char **)gDeviceNames; 1410 } 1411 1412 1413 device_hooks * 1414 find_device(const char *name) 1415 { 1416 TRACE("find_device()\n"); 1417 static device_hooks hooks = { 1418 &usb_disk_open, 1419 &usb_disk_close, 1420 &usb_disk_free, 1421 &usb_disk_ioctl, 1422 &usb_disk_read, 1423 &usb_disk_write, 1424 NULL, 1425 NULL, 1426 NULL, 1427 NULL 1428 }; 1429 1430 return &hooks; 1431 } 1432