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 <kernel.h> 20 #include <fs/devfs.h> 21 #include <util/AutoLock.h> 22 23 #include "scsi_sense.h" 24 #include "usb_disk_scsi.h" 25 26 27 #define DRIVER_NAME "usb_disk" 28 #define DEVICE_NAME_BASE "disk/usb/" 29 #define DEVICE_NAME DEVICE_NAME_BASE"%" B_PRIu32 "/%d/raw" 30 31 32 //#define TRACE_USB_DISK 33 #ifdef TRACE_USB_DISK 34 #define TRACE(x...) dprintf(DRIVER_NAME ": " x) 35 #define TRACE_ALWAYS(x...) dprintf(DRIVER_NAME ": " x) 36 #else 37 #define TRACE(x...) /* nothing */ 38 #define TRACE_ALWAYS(x...) dprintf(DRIVER_NAME ": " x) 39 #endif 40 41 42 int32 api_version = B_CUR_DRIVER_API_VERSION; 43 static usb_module_info *gUSBModule = NULL; 44 static disk_device *gDeviceList = NULL; 45 static uint32 gDeviceCount = 0; 46 static uint32 gLunCount = 0; 47 static mutex gDeviceListLock; 48 static char **gDeviceNames = NULL; 49 50 static const uint8 kDeviceIcon[] = { 51 0x6e, 0x63, 0x69, 0x66, 0x0a, 0x04, 0x01, 0x73, 0x05, 0x01, 0x02, 0x01, 52 0x06, 0x02, 0xb1, 0xf8, 0x5d, 0x3a, 0x2f, 0xbf, 0xbe, 0xdb, 0x67, 0xb6, 53 0x98, 0x06, 0x4b, 0x22, 0x15, 0x47, 0x13, 0x02, 0x00, 0xed, 0xed, 0xed, 54 0xff, 0xab, 0xbc, 0xc6, 0x02, 0x01, 0x06, 0x02, 0xb9, 0x82, 0x56, 0x32, 55 0x7d, 0xfb, 0xb8, 0x06, 0x39, 0xbe, 0xd9, 0xb5, 0x4b, 0x7d, 0x31, 0x4a, 56 0xa4, 0xe7, 0x00, 0xd1, 0xde, 0xe4, 0xff, 0x7a, 0x9c, 0xae, 0x02, 0x00, 57 0x16, 0x02, 0x38, 0xe9, 0xaa, 0x3b, 0x7b, 0x1d, 0xbf, 0xb0, 0xa6, 0x3d, 58 0x16, 0x76, 0x4b, 0x84, 0x81, 0x48, 0x37, 0x36, 0x00, 0x99, 0xff, 0x53, 59 0x02, 0x00, 0x16, 0x02, 0xba, 0x38, 0x9a, 0xb8, 0xef, 0x79, 0x3e, 0x34, 60 0x8b, 0xbf, 0x56, 0x52, 0x48, 0x2c, 0x61, 0x4c, 0x4e, 0xec, 0x00, 0x40, 61 0xff, 0x01, 0x05, 0xff, 0x05, 0x46, 0x02, 0x01, 0x16, 0x02, 0x35, 0xc2, 62 0x71, 0x3a, 0xf6, 0x84, 0xb9, 0xf3, 0x5b, 0x34, 0x81, 0xa0, 0x49, 0xc0, 63 0x57, 0x49, 0x6e, 0x51, 0xff, 0xf3, 0x00, 0x52, 0x02, 0x01, 0x06, 0x02, 64 0x38, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x80, 0x00, 65 0x49, 0xa0, 0x00, 0x49, 0x80, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x06, 66 0xe3, 0x06, 0x0c, 0x06, 0x09, 0xab, 0xaa, 0x03, 0x3e, 0x5e, 0x3c, 0x5f, 67 0x3e, 0x5e, 0x60, 0x4d, 0x5a, 0x4a, 0x60, 0x47, 0x56, 0x42, 0x50, 0x45, 68 0x4c, 0x43, 0x2a, 0x54, 0x36, 0x5d, 0x36, 0x5d, 0x3a, 0x60, 0x06, 0x08, 69 0xfb, 0xea, 0x27, 0x49, 0x26, 0x48, 0x27, 0x49, 0x32, 0x56, 0x37, 0x59, 70 0x37, 0x59, 0x38, 0x5a, 0x3b, 0x59, 0x3a, 0x5a, 0x3b, 0x59, 0x58, 0x3c, 71 0x52, 0x36, 0x43, 0x29, 0x27, 0x45, 0x27, 0x45, 0x26, 0x46, 0x06, 0x05, 72 0xab, 0x03, 0x27, 0x49, 0x26, 0x48, 0x27, 0x49, 0x32, 0x56, 0x52, 0x36, 73 0x43, 0x29, 0x27, 0x45, 0x27, 0x45, 0x26, 0x46, 0x0a, 0x05, 0xc2, 0x1c, 74 0xb8, 0xf9, 0x4f, 0x25, 0xc9, 0x4c, 0xb7, 0xc4, 0x5a, 0x30, 0x51, 0x39, 75 0x0a, 0x04, 0xc5, 0x50, 0xbb, 0xc0, 0xc2, 0x1c, 0xb8, 0xf9, 0x4f, 0x25, 76 0xc9, 0x4c, 0xb7, 0xc4, 0x0a, 0x04, 0x51, 0x39, 0xc5, 0x50, 0xbb, 0xc0, 77 0xc9, 0x4c, 0xb7, 0xc4, 0x5a, 0x30, 0x0a, 0x04, 0x4f, 0x2f, 0x51, 0x31, 78 0x53, 0x2f, 0x51, 0x2d, 0x06, 0x04, 0xee, 0x4f, 0x35, 0x53, 0x30, 0x51, 79 0x32, 0x55, 0x2e, 0x58, 0x2c, 0x54, 0x31, 0x56, 0x2f, 0x52, 0x33, 0x06, 80 0x04, 0xee, 0x31, 0x58, 0x40, 0x47, 0x39, 0x4e, 0x47, 0x40, 0x50, 0x38, 81 0x41, 0x48, 0x48, 0x41, 0x3a, 0x4f, 0x08, 0x02, 0x3a, 0x40, 0x3e, 0x3c, 82 0x02, 0x04, 0x3e, 0x3a, 0xbe, 0x48, 0x3a, 0xbf, 0x9f, 0x3a, 0x41, 0x3d, 83 0x41, 0xbd, 0xe2, 0x41, 0xbf, 0x39, 0x3e, 0x40, 0xbf, 0x9f, 0x40, 0xbe, 84 0x48, 0x40, 0x3b, 0x3d, 0x3b, 0xbf, 0x39, 0x3b, 0xbd, 0xe2, 0x06, 0x05, 85 0xbe, 0x02, 0x32, 0x56, 0x36, 0x5a, 0x36, 0x5a, 0x37, 0x5b, 0x3a, 0x5a, 86 0x39, 0x5b, 0x3a, 0x5a, 0x58, 0x3c, 0x52, 0x36, 0x11, 0x0a, 0x00, 0x01, 87 0x00, 0x00, 0x0a, 0x01, 0x01, 0x03, 0x12, 0x3f, 0xe9, 0x8e, 0xbb, 0x54, 88 0xe2, 0x3b, 0x54, 0xe2, 0x3f, 0xe9, 0x8e, 0xc6, 0x4d, 0xd9, 0x45, 0xc0, 89 0xc5, 0x01, 0x17, 0x84, 0x00, 0x04, 0x0a, 0x02, 0x01, 0x04, 0x02, 0x3f, 90 0xe9, 0x8e, 0xbb, 0x54, 0xe2, 0x3b, 0x54, 0xe2, 0x3f, 0xe9, 0x8e, 0xc6, 91 0x4d, 0xd9, 0x45, 0xc0, 0xc5, 0x0a, 0x03, 0x01, 0x05, 0x02, 0x3f, 0xe9, 92 0x8e, 0xbb, 0x54, 0xe2, 0x3b, 0x54, 0xe2, 0x3f, 0xe9, 0x8e, 0xc6, 0x4d, 93 0xd9, 0x45, 0xc0, 0xc5, 0x0a, 0x01, 0x01, 0x01, 0x12, 0x3f, 0xe9, 0x8e, 94 0xbb, 0x54, 0xe2, 0x3b, 0x54, 0xe2, 0x3f, 0xe9, 0x8e, 0xc6, 0xb0, 0x64, 95 0x46, 0x78, 0x3b, 0x01, 0x17, 0x84, 0x00, 0x04, 0x0a, 0x04, 0x01, 0x02, 96 0x02, 0x3f, 0xe9, 0x8e, 0xbb, 0x54, 0xe2, 0x3b, 0x54, 0xe2, 0x3f, 0xe9, 97 0x8e, 0xc6, 0xb0, 0x64, 0x46, 0x78, 0x3b, 0x0a, 0x05, 0x01, 0x0b, 0x02, 98 0x3f, 0xe9, 0x8e, 0xbb, 0x54, 0xe2, 0x3b, 0x54, 0xe2, 0x3f, 0xe9, 0x8e, 99 0xc6, 0xb0, 0x64, 0x46, 0x78, 0x3b, 0x0a, 0x01, 0x01, 0x06, 0x02, 0x3f, 100 0xe9, 0x8e, 0xbb, 0x54, 0xe2, 0x3b, 0x54, 0xe2, 0x3f, 0xe9, 0x8e, 0xc6, 101 0x5b, 0x2d, 0x45, 0x43, 0x93, 0x0a, 0x01, 0x01, 0x06, 0x02, 0x3f, 0xe9, 102 0x8e, 0xbb, 0x54, 0xe2, 0x3b, 0x54, 0xe2, 0x3f, 0xe9, 0x8e, 0xc7, 0x7d, 103 0x8b, 0x44, 0x36, 0x9a, 0x0a, 0x06, 0x02, 0x07, 0x08, 0x02, 0x3f, 0xe9, 104 0x8e, 0xbb, 0x54, 0xe2, 0x3b, 0x54, 0xe2, 0x3f, 0xe9, 0x8e, 0xc6, 0x4d, 105 0xd9, 0x45, 0xc0, 0xc5, 0x0a, 0x01, 0x01, 0x09, 0x12, 0x3f, 0x6c, 0x5c, 106 0xba, 0xea, 0x46, 0x3a, 0xea, 0x46, 0x3f, 0x6c, 0x5c, 0xc5, 0x19, 0x6c, 107 0x46, 0x6b, 0x36, 0x01, 0x17, 0x8c, 0x22, 0x04, 0x0a, 0x07, 0x01, 0x09, 108 0x12, 0x3f, 0xe9, 0x8e, 0xbb, 0x54, 0xe2, 0x3b, 0x54, 0xe2, 0x3f, 0xe9, 109 0x8e, 0xc6, 0x4d, 0xd9, 0x45, 0xc0, 0xc5, 0x01, 0x17, 0x88, 0x22, 0x04, 110 0x0a, 0x08, 0x01, 0x09, 0x12, 0x3f, 0xe9, 0x8e, 0xbb, 0x54, 0xe2, 0x3b, 111 0x54, 0xe2, 0x3f, 0xe9, 0x8e, 0xc6, 0x01, 0xed, 0x46, 0x11, 0xa8, 0x01, 112 0x17, 0x85, 0x22, 0x04, 0x0a, 0x01, 0x01, 0x0a, 0x12, 0x3f, 0xe9, 0x8e, 113 0xbb, 0x54, 0xe2, 0x3a, 0xaa, 0x52, 0x3f, 0x21, 0x43, 0xc6, 0x59, 0xd0, 114 0x46, 0xdb, 0x8c, 0x01, 0x17, 0x84, 0x00, 0x04, 0x0a, 0x06, 0x01, 0x0a, 115 0x02, 0x3f, 0xe9, 0x8e, 0xbb, 0x54, 0xe2, 0x3b, 0x54, 0xe2, 0x3f, 0xe9, 116 0x8e, 0xc6, 0x99, 0xc6, 0x45, 0x5e, 0x3a, 0x0a, 0x01, 0x01, 0x0a, 0x12, 117 0x3f, 0x21, 0x43, 0xba, 0xaa, 0x52, 0x3a, 0xaa, 0x52, 0x3f, 0x21, 0x43, 118 0xc7, 0xd2, 0xa7, 0x49, 0x5f, 0xed, 0x01, 0x17, 0x84, 0x00, 0x04, 0x0a, 119 0x09, 0x01, 0x0a, 0x02, 0x3f, 0xe9, 0x8e, 0xbb, 0x54, 0xe2, 0x3b, 0x54, 120 0xe2, 0x3f, 0xe9, 0x8e, 0xc8, 0xa5, 0xc8, 0x48, 0xeb, 0x05 121 }; 122 123 const unsigned char kCDIcon[] = { 124 0x6e, 0x63, 0x69, 0x66, 0x05, 0x05, 0x00, 0x02, 0x03, 0x06, 0x05, 0xb8, 125 0x12, 0xa5, 0xbe, 0x03, 0xe1, 0x3d, 0xe7, 0x84, 0xb8, 0x02, 0x10, 0x49, 126 0xf7, 0x9f, 0x49, 0xed, 0xd8, 0x00, 0xf1, 0xf1, 0xf1, 0x36, 0xd9, 0xdd, 127 0xf4, 0x8a, 0x99, 0x96, 0xb9, 0xb4, 0xb8, 0xbe, 0xdb, 0xff, 0xf4, 0xf4, 128 0xf4, 0x04, 0xeb, 0xd0, 0x02, 0x00, 0x06, 0x02, 0x3c, 0x92, 0xc0, 0x38, 129 0x8f, 0x5f, 0xb8, 0x54, 0x50, 0x3c, 0x57, 0x63, 0x48, 0xd8, 0xdf, 0x48, 130 0x89, 0x5b, 0x00, 0x41, 0x37, 0xa9, 0xff, 0xb9, 0xb9, 0xb9, 0x04, 0x01, 131 0x7e, 0x04, 0x02, 0x04, 0x3f, 0x2c, 0x4e, 0x2c, 0x30, 0x2c, 0x22, 0x40, 132 0x22, 0x34, 0x22, 0x4c, 0x3f, 0x54, 0x30, 0x54, 0x4e, 0x54, 0x5c, 0x40, 133 0x5c, 0x4c, 0x5c, 0x34, 0x02, 0x04, 0x3f, 0x3a, 0x43, 0x3a, 0x3b, 0x3a, 134 0x39, 0x3e, 0x39, 0x3c, 0x39, 0x40, 0x3f, 0x42, 0x3b, 0x42, 0x43, 0x42, 135 0x45, 0x3e, 0x45, 0x40, 0x45, 0x3c, 0x02, 0x04, 0x4b, 0x3e, 0x4b, 0x3a, 136 0x4b, 0x42, 0x3f, 0x46, 0x47, 0x46, 0x37, 0x46, 0x33, 0x3e, 0x33, 0x42, 137 0x33, 0x3a, 0x3f, 0xbb, 0xf7, 0x37, 0xbb, 0xf7, 0x47, 0xbb, 0xf7, 0x02, 138 0x04, 0x40, 0x2a, 0x54, 0x2a, 0x50, 0x2c, 0x5c, 0x40, 0x5c, 0x34, 0x5c, 139 0x4c, 0x40, 0x56, 0x50, 0x54, 0x54, 0x56, 0x60, 0x40, 0x60, 0x4c, 0x60, 140 0x34, 0x06, 0x0a, 0x04, 0x01, 0x03, 0x00, 0x0a, 0x00, 0x02, 0x00, 0x01, 141 0x18, 0x15, 0xff, 0x01, 0x17, 0x84, 0x00, 0x04, 0x0a, 0x00, 0x02, 0x00, 142 0x01, 0x18, 0x00, 0x15, 0x01, 0x17, 0x86, 0x00, 0x04, 0x0a, 0x01, 0x02, 143 0x00, 0x02, 0x00, 0x0a, 0x02, 0x02, 0x02, 0x01, 0x00, 0x0a, 0x03, 0x01, 144 0x02, 0x10, 0x01, 0x17, 0x82, 0x00, 0x04 145 }; 146 147 const unsigned char kMemoryStickIcon[] = { 148 0x6e, 0x63, 0x69, 0x66, 0x09, 0x05, 0x00, 0x04, 0x00, 0x63, 0x02, 0x00, 149 0x06, 0x02, 0x3a, 0x9c, 0xfb, 0x3b, 0x07, 0x44, 0xbd, 0x68, 0x2d, 0x3c, 150 0xf0, 0x9a, 0x49, 0x8c, 0xd7, 0x4a, 0x02, 0xf0, 0x00, 0x67, 0x72, 0xc0, 151 0xff, 0x5e, 0x68, 0xae, 0x02, 0x00, 0x06, 0x02, 0x39, 0xd8, 0xc8, 0x38, 152 0x57, 0x6f, 0xbb, 0x1e, 0xa3, 0x3c, 0x90, 0x06, 0x4b, 0x3b, 0x28, 0x49, 153 0x91, 0x9a, 0x00, 0x55, 0x55, 0x84, 0xff, 0x73, 0x79, 0xaa, 0x02, 0x00, 154 0x06, 0x02, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 155 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xba, 0xbf, 0xed, 156 0xff, 0x81, 0x8b, 0xd9, 0x02, 0x00, 0x06, 0x02, 0x3d, 0x00, 0x00, 0x00, 157 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x4a, 0x00, 0x00, 0xa1, 158 0x24, 0x8d, 0x00, 0xbd, 0xc1, 0xe9, 0xfe, 0x83, 0x8d, 0xdc, 0x03, 0xc3, 159 0xca, 0xff, 0x03, 0x08, 0x13, 0x47, 0x03, 0x08, 0x13, 0x47, 0x0d, 0x0a, 160 0x04, 0x5e, 0xbc, 0x52, 0x3c, 0x5a, 0x42, 0x5a, 0x62, 0xbd, 0x1e, 0x0a, 161 0x06, 0x22, 0x46, 0x22, 0x4b, 0x3c, 0x58, 0x5e, 0x36, 0x5e, 0x32, 0x46, 162 0x2a, 0x06, 0x08, 0xfe, 0x9b, 0x3c, 0x52, 0xbc, 0xae, 0xc6, 0x3d, 0xbd, 163 0x92, 0xc6, 0xa6, 0xbc, 0x79, 0xc6, 0x25, 0x37, 0x52, 0xbc, 0x66, 0xc7, 164 0x08, 0xba, 0x74, 0xc6, 0x22, 0x26, 0x4a, 0xb7, 0x26, 0xc4, 0x8c, 0xb5, 165 0x34, 0xc3, 0xa6, 0xb5, 0x9e, 0xc2, 0xfb, 0xb5, 0xc9, 0xc3, 0x0f, 0xb4, 166 0x89, 0xc2, 0x7b, 0x22, 0x46, 0x4b, 0x3c, 0x58, 0x0a, 0x04, 0x3c, 0x52, 167 0x5e, 0x32, 0x5e, 0x36, 0x3c, 0x58, 0x0a, 0x04, 0x3c, 0x52, 0x5e, 0x32, 168 0x46, 0x2a, 0x22, 0x47, 0x06, 0x07, 0xaa, 0x39, 0xc4, 0x10, 0xbf, 0x1a, 169 0xbc, 0xac, 0xc5, 0xbc, 0x37, 0x50, 0x38, 0x51, 0x50, 0xc4, 0xbc, 0xbe, 170 0xcb, 0x40, 0x38, 0xbf, 0xe4, 0xbc, 0x7f, 0xbf, 0x8f, 0xbc, 0xa6, 0x06, 171 0x08, 0xaa, 0xab, 0xb5, 0xeb, 0xc3, 0x48, 0xbe, 0x7b, 0xbc, 0x6a, 0xbe, 172 0x67, 0xbb, 0xbb, 0xb5, 0x3f, 0xc3, 0x31, 0x26, 0x4a, 0xb5, 0x2e, 0xc3, 173 0xa5, 0xb6, 0x74, 0xc4, 0x2f, 0x37, 0x52, 0x38, 0x51, 0x30, 0x4d, 0x0a, 174 0x04, 0x38, 0x50, 0x4a, 0x3e, 0x3c, 0x38, 0xb5, 0xeb, 0xc3, 0x48, 0x06, 175 0x0d, 0xf6, 0xff, 0xff, 0x03, 0xcc, 0x52, 0xbd, 0x0d, 0xbd, 0x16, 0xca, 176 0xee, 0xbd, 0x16, 0xca, 0xee, 0xbd, 0x16, 0xca, 0x64, 0xbd, 0x01, 0xc9, 177 0xf8, 0xbc, 0x36, 0xca, 0x10, 0xbc, 0xb6, 0xc9, 0xbc, 0xbb, 0xb5, 0xc8, 178 0xf4, 0xbc, 0x36, 0xc8, 0xf4, 0xbb, 0xd9, 0xc9, 0x21, 0xbc, 0xb6, 0xc8, 179 0x70, 0xbd, 0x16, 0xc8, 0xf7, 0xbd, 0x01, 0xc7, 0xff, 0xbd, 0x13, 0xc7, 180 0xea, 0xbc, 0x36, 0xc7, 0xbd, 0xbc, 0xda, 0xc7, 0xea, 0xbb, 0xd9, 0xc6, 181 0xd3, 0xbc, 0x36, 0xc7, 0x24, 0xbb, 0xbb, 0xc6, 0xa6, 0xbc, 0xb0, 0xc5, 182 0xdb, 0xbd, 0x16, 0xc6, 0x56, 0xbc, 0xfb, 0xc5, 0xdb, 0xbd, 0x16, 0xc4, 183 0x5f, 0xbd, 0x16, 0xc4, 0x5f, 0xbd, 0x16, 0xc5, 0x24, 0xbc, 0xcb, 0xc6, 184 0x2f, 0xbb, 0xd9, 0xc5, 0xcf, 0xbc, 0x6c, 0xc7, 0xa8, 0xbb, 0x82, 0xca, 185 0x94, 0xbb, 0xd9, 0xc9, 0x1e, 0xbb, 0x7c, 0xca, 0xfa, 0xbc, 0x69, 0xcc, 186 0x52, 0xbd, 0x0d, 0xcb, 0x92, 0xbc, 0xcb, 0xcc, 0x52, 0xbd, 0x0d, 0x06, 187 0x04, 0xfe, 0xcc, 0x52, 0xbd, 0x91, 0xcc, 0x52, 0xbd, 0x94, 0xcc, 0x52, 188 0xbd, 0x94, 0xc9, 0xa7, 0xbd, 0xee, 0xc4, 0x5f, 0xbd, 0x91, 0xc7, 0x00, 189 0xbd, 0xee, 0xc7, 0x12, 0xbd, 0x55, 0xcc, 0x52, 0xbd, 0x91, 0xc9, 0xb3, 190 0xbd, 0x52, 0xcc, 0x52, 0xbd, 0x91, 0x02, 0x03, 0xc5, 0x75, 0xbe, 0x50, 191 0xc5, 0x75, 0xbe, 0x50, 0xc7, 0x75, 0xbe, 0x24, 0xcb, 0x50, 0xbe, 0x50, 192 0xc9, 0x63, 0xbe, 0x24, 0xc9, 0x5a, 0xbe, 0x92, 0xc5, 0x75, 0xbe, 0x50, 193 0xc7, 0x66, 0xbe, 0x92, 0xc5, 0x75, 0xbe, 0x50, 0x02, 0x02, 0xc6, 0x2f, 194 0xbe, 0xdd, 0xc7, 0xa5, 0xbf, 0x22, 0xc7, 0xae, 0xbe, 0xb3, 0xca, 0x97, 195 0xbe, 0xdd, 0xc9, 0x24, 0xbe, 0xb0, 0xc9, 0x1e, 0xbf, 0x22, 0x0a, 0x03, 196 0x45, 0x2d, 0x4a, 0x2f, 0x4a, 0x2c, 0x0a, 0x0a, 0x01, 0x01, 0x00, 0x00, 197 0x0a, 0x00, 0x01, 0x01, 0x10, 0x01, 0x17, 0x84, 0x00, 0x04, 0x0a, 0x02, 198 0x01, 0x02, 0x00, 0x0a, 0x03, 0x01, 0x03, 0x00, 0x0a, 0x04, 0x01, 0x04, 199 0x00, 0x0a, 0x03, 0x01, 0x06, 0x00, 0x0a, 0x06, 0x01, 0x05, 0x00, 0x0a, 200 0x05, 0x01, 0x07, 0x00, 0x0a, 0x07, 0x04, 0x09, 0x0a, 0x0b, 0x08, 0x02, 201 0xbe, 0x56, 0x60, 0x3e, 0x5e, 0xcf, 0xbe, 0x5e, 0xcf, 0xbe, 0x56, 0x60, 202 0x4c, 0xe9, 0x91, 0x41, 0xdd, 0x95, 0x0a, 0x08, 0x01, 0x0c, 0x00 203 }; 204 205 206 const unsigned char kSDIcon[] = { 207 0x6e, 0x63, 0x69, 0x66, 0x09, 0x05, 0x00, 0x04, 0x00, 0x63, 0x02, 0x00, 208 0x06, 0x02, 0x3a, 0x9c, 0xfb, 0x3b, 0x07, 0x44, 0xbd, 0x68, 0x2d, 0x3c, 209 0xf0, 0x9a, 0x49, 0x8c, 0xd7, 0x4a, 0x02, 0xf0, 0x00, 0xa4, 0xa4, 0xa4, 210 0xff, 0x5a, 0x5b, 0x65, 0x02, 0x00, 0x16, 0x02, 0x39, 0xd8, 0xc8, 0x38, 211 0x57, 0x6f, 0xbb, 0x1e, 0xa3, 0x3c, 0x90, 0x06, 0x4b, 0x3b, 0x28, 0x49, 212 0x91, 0x9a, 0x00, 0x55, 0xff, 0x39, 0x02, 0x00, 0x16, 0x02, 0x3d, 0x00, 213 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x4a, 0x00, 214 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0xff, 0x5b, 0x02, 0x00, 0x06, 0x02, 215 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 216 0x4a, 0x00, 0x00, 0xa1, 0x24, 0x8d, 0x00, 0xe5, 0xe7, 0xf9, 0xfe, 0xb3, 217 0xb5, 0xc3, 0x05, 0xc6, 0x03, 0x08, 0x13, 0x47, 0x05, 0xff, 0x0e, 0x0a, 218 0x04, 0x60, 0xc0, 0x4e, 0x44, 0x5e, 0x4a, 0x5e, 0x60, 0x47, 0x0a, 0x0c, 219 0x22, 0x46, 0x22, 0x48, 0x22, 0x4b, 0x44, 0x5c, 0xca, 0x15, 0xc2, 0x2a, 220 0x59, 0x45, 0x5b, 0x43, 0x5c, 0x44, 0x5e, 0x42, 0x5e, 0x3e, 0xcb, 0x07, 221 0x33, 0x46, 0x2a, 0x06, 0x08, 0xfe, 0x9b, 0x44, 0x56, 0xbf, 0xde, 0xc7, 222 0xd5, 0xc0, 0xc2, 0xc8, 0x3e, 0xbf, 0xa9, 0xc7, 0xbd, 0x3f, 0x56, 0xbf, 223 0x96, 0xc8, 0xa0, 0xbd, 0xa4, 0xc7, 0xba, 0x26, 0x4a, 0xb7, 0x26, 0xc4, 224 0x8c, 0xb5, 0x34, 0xc3, 0xa6, 0xb5, 0x9e, 0xc2, 0xfb, 0xb5, 0xc9, 0xc3, 225 0x0f, 0xb4, 0x89, 0xc2, 0x7b, 0x22, 0x46, 0x4b, 0x44, 0x5c, 0x0a, 0x0c, 226 0x44, 0x56, 0xca, 0x87, 0xbf, 0xe4, 0x5a, 0xbf, 0x83, 0x5b, 0xbf, 0x1d, 227 0xca, 0xe7, 0xbf, 0x92, 0x5e, 0x3e, 0x5e, 0x42, 0xca, 0xeb, 0xc1, 0x54, 228 0xca, 0x85, 0xc0, 0xf5, 0x5a, 0x44, 0xca, 0x86, 0xc1, 0xb9, 0x44, 0x5c, 229 0x0a, 0x0d, 0x44, 0x56, 0xca, 0x8f, 0xbf, 0xf3, 0x5a, 0xbf, 0x93, 0xca, 230 0x90, 0xbf, 0x22, 0xca, 0xf3, 0xbf, 0x9e, 0x5e, 0x3e, 0xcb, 0x09, 0xba, 231 0x91, 0x46, 0x2a, 0xc0, 0x1e, 0xb8, 0x9c, 0x41, 0x2f, 0x3b, 0x34, 0xbd, 232 0x91, 0xba, 0xab, 0x22, 0x47, 0x06, 0x07, 0xaa, 0x39, 0xc9, 0xa4, 0xbf, 233 0x80, 0xc0, 0xa8, 0xc7, 0xba, 0x41, 0x55, 0x42, 0x56, 0x55, 0xca, 0x50, 234 0xbf, 0x31, 0x44, 0x34, 0xc1, 0x7c, 0xba, 0xe7, 0xc1, 0x27, 0xbb, 0x0e, 235 0x06, 0x08, 0xaa, 0xab, 0xb5, 0x1f, 0xc2, 0xe2, 0xbf, 0xad, 0xba, 0xd2, 236 0xbf, 0x99, 0xba, 0x23, 0xb4, 0x73, 0xc2, 0xcb, 0x24, 0x49, 0xb4, 0x62, 237 0xc3, 0x3f, 0xb5, 0xa8, 0xc3, 0xc9, 0x40, 0x57, 0x41, 0x56, 0x32, 0x4e, 238 0x0a, 0x04, 0x40, 0x55, 0x58, 0x3f, 0x40, 0x33, 0xb5, 0x85, 0xc2, 0xe2, 239 0x0a, 0x03, 0x44, 0x2d, 0x46, 0x2f, 0x42, 0x31, 0x0a, 0x08, 0x47, 0x30, 240 0x47, 0x31, 0x49, 0x32, 0x4a, 0x32, 0x4a, 0x34, 0x49, 0x34, 0x47, 0x33, 241 0x45, 0x32, 0x04, 0x0f, 0xaf, 0xff, 0xeb, 0x3f, 0xc9, 0x8a, 0xc3, 0xb2, 242 0xc9, 0x8a, 0xc3, 0xb2, 0xc9, 0x8a, 0xc4, 0xc4, 0xc3, 0x50, 0xc4, 0xc4, 243 0xc7, 0xed, 0xc4, 0xda, 0xbc, 0x23, 0xc4, 0xa6, 0xb6, 0x1e, 0xc3, 0xee, 244 0xb3, 0x4d, 0xcb, 0xb1, 0xc1, 0x6c, 0xcc, 0x29, 0xba, 0x22, 0xcc, 0x29, 245 0xcb, 0xd2, 0xcc, 0x29, 0xd5, 0xf5, 0xc5, 0xb4, 0xd4, 0x64, 0xcc, 0x92, 246 0xd7, 0x12, 0xc0, 0xdb, 0xcd, 0xcd, 0xbd, 0x13, 0xd2, 0xd7, 0xbe, 0x92, 247 0xca, 0x67, 0xbc, 0x11, 0xc4, 0x35, 0xb9, 0x75, 0xc4, 0x35, 0xba, 0xac, 248 0xc4, 0x35, 0xb7, 0xe8, 0xcb, 0x40, 0xb7, 0xdc, 0xc8, 0x5e, 0xb7, 0xf3, 249 0xce, 0x66, 0xb7, 0xc6, 0xda, 0x9a, 0xb7, 0xc2, 0xdc, 0x27, 0xb3, 0x5d, 250 0xca, 0xaa, 0xb3, 0x8e, 0xd3, 0x61, 0xb3, 0x21, 0xbe, 0x1d, 0xb4, 0x2f, 251 0xbb, 0x7a, 0xb9, 0xa2, 0xbb, 0xc5, 0xb6, 0xf8, 0xbb, 0x18, 0xbd, 0x17, 252 0xc2, 0x95, 0xc0, 0x93, 0xbf, 0xc1, 0xbf, 0x7e, 0xc5, 0x46, 0xc1, 0x9a, 253 0xc9, 0x8a, 0xc3, 0xb2, 0xc9, 0x8a, 0xc2, 0x5d, 0xc9, 0x8a, 0xc3, 0xb2, 254 0x00, 0x0c, 0xeb, 0x0d, 0xbb, 0x77, 0xeb, 0x0d, 0xbb, 0x77, 0xea, 0xfe, 255 0xbb, 0x59, 0xea, 0xd8, 0xbb, 0x1d, 0xea, 0xeb, 0xbb, 0x3b, 0xea, 0xd8, 256 0xbb, 0x1d, 0xf9, 0xf9, 0xb7, 0x4e, 0xf9, 0xf9, 0xb7, 0x4e, 0xfc, 0x60, 257 0xb8, 0x7a, 0xff, 0x6c, 0xbb, 0xeb, 0xfe, 0x62, 0xb9, 0xfc, 0xff, 0x80, 258 0xbd, 0x9e, 0xff, 0x16, 0xc1, 0x17, 0xff, 0x80, 0xbf, 0x60, 0xf6, 0x6e, 259 0xcb, 0xd7, 0xd7, 0xca, 0xcc, 0x22, 0xdf, 0xeb, 0xcb, 0xc4, 0xd7, 0xca, 260 0xcc, 0x22, 0xdb, 0x52, 0xc2, 0x30, 0xdb, 0x52, 0xc2, 0x30, 0xdd, 0x79, 261 0xc2, 0x1d, 0xe2, 0x70, 0xc1, 0x71, 0xe0, 0x94, 0xc1, 0xce, 0xe4, 0x48, 262 0xc1, 0x13, 0xe7, 0x49, 0xc0, 0x05, 0xe5, 0xf0, 0xc0, 0x97, 0xe8, 0xa2, 263 0xbf, 0x73, 0xea, 0x5c, 0xbe, 0x1d, 0xe9, 0xb0, 0xbe, 0xce, 0xeb, 0x05, 264 0xbd, 0x6d, 0xeb, 0x36, 0xbb, 0xfe, 0xeb, 0x58, 0xbc, 0xb9, 0xeb, 0x2e, 265 0xbb, 0xd1, 0xeb, 0x0d, 0xbb, 0x77, 0xeb, 0x1f, 0xbb, 0xa4, 0xeb, 0x0d, 266 0xbb, 0x77, 0x04, 0x06, 0xff, 0x0b, 0xf6, 0xc4, 0xb5, 0xfc, 0xf6, 0xc4, 267 0xb5, 0xfc, 0xf5, 0xe3, 0xb5, 0x9f, 0xf3, 0xc7, 0xb4, 0xee, 0xf4, 0xac, 268 0xb5, 0x2a, 0xf3, 0xc7, 0xb4, 0xee, 0xe8, 0xb5, 0xb9, 0x66, 0xe8, 0xb5, 269 0xb9, 0x66, 0xe9, 0x07, 0xb9, 0x8f, 0xe9, 0xc3, 0xba, 0x16, 0xe9, 0x83, 270 0xb9, 0xed, 0xe9, 0xd5, 0xba, 0x25, 0xe9, 0xf7, 0xba, 0x3c, 0xe9, 0xe4, 271 0xba, 0x31, 0xe9, 0xf7, 0xba, 0x3c, 0xf6, 0xc4, 0xb5, 0xfc, 0x04, 0x07, 272 0xff, 0x2f, 0xed, 0xb0, 0xb3, 0xe8, 0xed, 0xb0, 0xb3, 0xe8, 0xeb, 0xdb, 273 0xb3, 0xa5, 0xe9, 0x70, 0xb3, 0x7f, 0xea, 0x55, 0xb3, 0x87, 0xe5, 0xe8, 274 0xb3, 0x69, 0xe0, 0x97, 0xb3, 0x5a, 0xe4, 0x84, 0xb3, 0x56, 0xe0, 0x97, 275 0xb3, 0x5a, 0xdf, 0x06, 0xb7, 0xc6, 0xdf, 0x06, 0xb7, 0xc6, 0xdf, 0xfe, 276 0xb7, 0xcd, 0xe2, 0x0e, 0xb7, 0xeb, 0xe0, 0x6e, 0xb7, 0xc2, 0xe3, 0x8d, 277 0xb8, 0x11, 0xe6, 0x24, 0xb8, 0x9c, 0xe4, 0xed, 0xb8, 0x49, 0xe6, 0x24, 278 0xb8, 0x9c, 0xed, 0xb0, 0xb3, 0xe8, 0x0d, 0x0a, 0x01, 0x01, 0x00, 0x00, 279 0x0a, 0x00, 0x01, 0x01, 0x10, 0x01, 0x17, 0x84, 0x00, 0x04, 0x0a, 0x02, 280 0x01, 0x02, 0x00, 0x0a, 0x03, 0x01, 0x03, 0x00, 0x0a, 0x04, 0x01, 0x04, 281 0x00, 0x0a, 0x03, 0x01, 0x06, 0x00, 0x0a, 0x06, 0x01, 0x05, 0x00, 0x0a, 282 0x05, 0x01, 0x07, 0x00, 0x0a, 0x00, 0x01, 0x0a, 0x02, 0x3a, 0x19, 0xca, 283 0x38, 0x20, 0xc9, 0xb8, 0x20, 0xc9, 0x3a, 0x19, 0xca, 0x49, 0x04, 0x3f, 284 0x48, 0xbc, 0x82, 0x0a, 0x00, 0x01, 0x0b, 0x02, 0x3a, 0x19, 0xca, 0x38, 285 0x20, 0xc9, 0xb8, 0x20, 0xc9, 0x3a, 0x19, 0xca, 0x49, 0x04, 0x3f, 0x48, 286 0xbc, 0x82, 0x0a, 0x00, 0x01, 0x0c, 0x02, 0x3a, 0x19, 0xca, 0x38, 0x20, 287 0xc9, 0xb8, 0x20, 0xc9, 0x3a, 0x19, 0xca, 0x49, 0x04, 0x3f, 0x48, 0xbc, 288 0x82, 0x0a, 0x00, 0x01, 0x0d, 0x02, 0x3a, 0x19, 0xca, 0x38, 0x20, 0xc9, 289 0xb8, 0x20, 0xc9, 0x3a, 0x19, 0xca, 0x49, 0x04, 0x3f, 0x48, 0xbc, 0x82, 290 0x0a, 0x08, 0x02, 0x08, 0x09, 0x00 291 }; 292 293 const unsigned char kMobileIcon[] = { 294 0x6e, 0x63, 0x69, 0x66, 0x09, 0x05, 0x00, 0x04, 0x00, 0x66, 0x02, 0x00, 295 0x06, 0x02, 0x38, 0xf1, 0x86, 0x38, 0x62, 0x09, 0xba, 0xd4, 0x58, 0x3b, 296 0x7e, 0xb7, 0x4a, 0x28, 0x8f, 0x47, 0xaf, 0x7c, 0x00, 0xee, 0xef, 0xf3, 297 0xff, 0xce, 0xd2, 0xd9, 0x02, 0x00, 0x06, 0x03, 0x39, 0x3a, 0x47, 0xba, 298 0x81, 0x7b, 0x3f, 0x5c, 0xe7, 0x3e, 0x2a, 0x74, 0xc5, 0xab, 0xe0, 0x49, 299 0x3b, 0x67, 0x00, 0xff, 0xff, 0xff, 0x42, 0xd9, 0xde, 0xe5, 0xff, 0xb5, 300 0xb8, 0xbf, 0x02, 0x00, 0x06, 0x02, 0x38, 0xdc, 0xc0, 0x32, 0xb6, 0x96, 301 0xb9, 0xc3, 0xec, 0x3f, 0xf8, 0xe2, 0x4a, 0x00, 0x51, 0xb9, 0x4b, 0xdc, 302 0x00, 0xce, 0xd2, 0xd9, 0xff, 0x95, 0x9a, 0xa6, 0x02, 0x03, 0x06, 0x04, 303 0xba, 0x6c, 0x40, 0xb8, 0x55, 0xde, 0xbb, 0x7a, 0x07, 0x3d, 0x9b, 0x59, 304 0x49, 0xea, 0xb7, 0x49, 0x0b, 0x3e, 0x20, 0xda, 0xde, 0xe5, 0x52, 0xff, 305 0xff, 0xff, 0xa4, 0xff, 0xff, 0xff, 0xff, 0x95, 0x9a, 0xa6, 0x05, 0xff, 306 0x02, 0x00, 0x06, 0x03, 0x38, 0x2d, 0xf0, 0x3a, 0x3d, 0xb3, 0xbf, 0x98, 307 0xe5, 0x3d, 0x7f, 0x98, 0x4b, 0xc7, 0x2b, 0x44, 0x03, 0xbe, 0x00, 0x9e, 308 0xc9, 0xff, 0xb2, 0x60, 0x99, 0xde, 0xff, 0x7f, 0xb0, 0xef, 0x03, 0x73, 309 0x79, 0x80, 0x15, 0x0a, 0x0a, 0x29, 0x54, 0x39, 0x5e, 0x3c, 0x5c, 0x3d, 310 0x5a, 0x46, 0x53, 0x47, 0x53, 0x59, 0x44, 0x59, 0x43, 0x4a, 0x3c, 0x29, 311 0x52, 0x0a, 0x08, 0x4a, 0x39, 0x4b, 0x3a, 0x3a, 0x5c, 0x38, 0x5c, 0x27, 312 0x52, 0x29, 0x4e, 0x2a, 0x4d, 0x38, 0x31, 0x0a, 0x0a, 0x4a, 0x39, 0x3b, 313 0x57, 0x39, 0x59, 0x37, 0x59, 0x36, 0x5a, 0x29, 0x52, 0x27, 0x52, 0x29, 314 0x4e, 0x2a, 0x4d, 0x38, 0x31, 0x0a, 0x0a, 0x27, 0x52, 0x29, 0x52, 0x36, 315 0x5a, 0x37, 0x59, 0x39, 0x59, 0x3b, 0x57, 0x4a, 0x39, 0x4b, 0x3a, 0x3a, 316 0x5c, 0x38, 0x5c, 0x08, 0x02, 0x35, 0x45, 0x2e, 0x51, 0x08, 0x02, 0x3b, 317 0x48, 0x34, 0x54, 0x08, 0x02, 0x3b, 0x53, 0x2d, 0x4b, 0x08, 0x02, 0x2f, 318 0x47, 0x3d, 0x4e, 0x0a, 0x08, 0x31, 0x42, 0x30, 0x40, 0x3f, 0x22, 0x52, 319 0x29, 0x52, 0x2a, 0x43, 0x48, 0x42, 0x49, 0x3f, 0x49, 0x0a, 0x0a, 0x31, 320 0x42, 0x30, 0x40, 0x3f, 0x22, 0x52, 0x29, 0x52, 0x2a, 0x43, 0x48, 0x42, 321 0x49, 0x3f, 0x49, 0x50, 0x29, 0x3f, 0x23, 0x0a, 0x04, 0x31, 0x42, 0x3f, 322 0x23, 0x50, 0x29, 0x3f, 0x49, 0x0a, 0x04, 0x48, 0x28, 0x47, 0x29, 0x44, 323 0x28, 0x45, 0x27, 0x0a, 0x04, 0x43, 0x26, 0x44, 0x25, 0x4b, 0x28, 0x4a, 324 0x29, 0x0a, 0x04, 0x4c, 0x2c, 0x44, 0x3c, 0x38, 0x36, 0x3f, 0x27, 0x0a, 325 0x04, 0x39, 0x3e, 0x3c, 0x40, 0x3d, 0x3e, 0xbd, 0x62, 0xbe, 0x44, 0x08, 326 0x02, 0x37, 0x40, 0x3c, 0x43, 0x08, 0x02, 0x36, 0x42, 0x3a, 0x39, 0x08, 327 0x02, 0x35, 0x3d, 0x37, 0x3e, 0x08, 0x02, 0x3b, 0x45, 0x40, 0x3c, 0x08, 328 0x02, 0x40, 0x43, 0x3d, 0x41, 0x08, 0x03, 0x38, 0x36, 0x3f, 0x27, 0x4c, 329 0x2c, 0x0f, 0x0a, 0x01, 0x01, 0x00, 0x10, 0x01, 0x15, 0x84, 0x00, 0x04, 330 0x0a, 0x00, 0x01, 0x01, 0x18, 0x00, 0x15, 0x01, 0x17, 0x86, 0x02, 0x04, 331 0x0a, 0x00, 0x01, 0x01, 0x18, 0x15, 0xff, 0x01, 0x17, 0x84, 0x02, 0x04, 332 0x0a, 0x03, 0x01, 0x02, 0x00, 0x0a, 0x04, 0x01, 0x03, 0x00, 0x0a, 0x08, 333 0x04, 0x04, 0x05, 0x06, 0x07, 0x18, 0x15, 0xff, 0x01, 0x17, 0x81, 0x00, 334 0x04, 0x0a, 0x00, 0x01, 0x08, 0x18, 0x00, 0x15, 0x01, 0x17, 0x86, 0x02, 335 0x04, 0x0a, 0x00, 0x01, 0x08, 0x18, 0x15, 0xff, 0x01, 0x17, 0x84, 0x02, 336 0x04, 0x0a, 0x05, 0x01, 0x09, 0x00, 0x0a, 0x02, 0x01, 0x0a, 0x00, 0x0a, 337 0x00, 0x01, 0x0b, 0x08, 0x15, 0xff, 0x0a, 0x06, 0x01, 0x0c, 0x08, 0x15, 338 0xff, 0x0a, 0x07, 0x01, 0x0d, 0x00, 0x0a, 0x06, 0x01, 0x0e, 0x08, 0x15, 339 0xff, 0x0a, 0x08, 0x06, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x14, 0x18, 0x15, 340 0xff, 0x01, 0x17, 0x81, 0x00, 0x04 341 }; 342 343 const unsigned char kZipIcon[] = { 344 0x6e, 0x63, 0x69, 0x66, 0x0d, 0x03, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 345 0x00, 0x6a, 0x02, 0x00, 0x06, 0x02, 0x38, 0x6a, 0xad, 0x38, 0xeb, 0x7a, 346 0xbb, 0x77, 0x73, 0x3a, 0xde, 0x88, 0x48, 0xce, 0xdc, 0x4a, 0x75, 0xed, 347 0x00, 0x1e, 0x31, 0x8d, 0xff, 0x27, 0x29, 0x91, 0x02, 0x00, 0x06, 0x02, 348 0x38, 0x6a, 0xad, 0x38, 0xeb, 0x7a, 0xbb, 0x77, 0x73, 0x3a, 0xde, 0x88, 349 0x48, 0xce, 0xdc, 0x4a, 0x75, 0xed, 0x00, 0x8a, 0x8a, 0x8a, 0xff, 0x0f, 350 0x0d, 0x7a, 0x05, 0x7d, 0x02, 0x00, 0x06, 0x02, 0x39, 0xc6, 0x30, 0x36, 351 0xa8, 0x1b, 0xb9, 0x51, 0xe6, 0x3c, 0x5b, 0xb3, 0x4b, 0x4d, 0xa8, 0x4a, 352 0x1a, 0xa1, 0x00, 0x16, 0x34, 0x77, 0xff, 0x23, 0x23, 0x84, 0x02, 0x00, 353 0x06, 0x02, 0xb7, 0x16, 0xa4, 0xba, 0x87, 0xfe, 0x3c, 0xb2, 0x07, 0xb9, 354 0x49, 0xed, 0x48, 0x87, 0xd8, 0x4a, 0x1e, 0x62, 0x01, 0x15, 0x37, 0xca, 355 0xfe, 0x5e, 0x5e, 0xf8, 0x02, 0x00, 0x06, 0x02, 0xb7, 0x16, 0xa4, 0xba, 356 0x87, 0xfe, 0x3c, 0xb2, 0x07, 0xb9, 0x49, 0xed, 0x48, 0x87, 0xd8, 0x4a, 357 0x1e, 0x62, 0x00, 0x24, 0x36, 0x95, 0xfe, 0x17, 0x14, 0x80, 0x02, 0x00, 358 0x16, 0x05, 0x36, 0xef, 0x60, 0x38, 0xe2, 0xe5, 0xbd, 0x22, 0x41, 0x3b, 359 0x2f, 0xce, 0x4a, 0x0e, 0x78, 0x4a, 0x5a, 0x6c, 0x00, 0xb8, 0x38, 0xe6, 360 0x77, 0xb8, 0xbd, 0xd2, 0xff, 0x93, 0x02, 0x00, 0x16, 0x05, 0x34, 0x0a, 361 0x8f, 0x38, 0xd2, 0xa2, 0xba, 0xb4, 0xc5, 0x35, 0xe9, 0xec, 0x49, 0xfd, 362 0x24, 0x4a, 0x64, 0x62, 0x00, 0xe1, 0x38, 0xff, 0x75, 0xd7, 0xba, 0xf3, 363 0xfd, 0xd0, 0x02, 0x00, 0x16, 0x02, 0x36, 0x67, 0xbe, 0x39, 0xdd, 0xbc, 364 0xbe, 0x50, 0x04, 0x3a, 0xe0, 0x9f, 0x4b, 0x85, 0x01, 0x49, 0x2a, 0x3f, 365 0x00, 0xff, 0xff, 0xd8, 0x03, 0x38, 0x6d, 0xbe, 0x02, 0x00, 0x16, 0x02, 366 0x3c, 0x40, 0xef, 0x3b, 0x82, 0xd1, 0xba, 0xeb, 0x42, 0x3b, 0xbf, 0x4d, 367 0x4a, 0xa7, 0xce, 0x49, 0x5d, 0xc1, 0xff, 0x01, 0x00, 0x4a, 0x12, 0x0a, 368 0x05, 0x44, 0x5a, 0x44, 0x40, 0x5e, 0x40, 0x5f, 0x45, 0x49, 0x5a, 0x0a, 369 0x06, 0x45, 0x58, 0x5c, 0x42, 0x5c, 0x40, 0x3d, 0x34, 0xb5, 0x6b, 0xc2, 370 0x2e, 0xb5, 0x63, 0xc3, 0xbb, 0x0a, 0x04, 0x44, 0x58, 0x26, 0x4a, 0x26, 371 0x47, 0x44, 0x54, 0x0a, 0x04, 0x44, 0x59, 0x5c, 0x42, 0x5c, 0x3e, 0x44, 372 0x54, 0x0a, 0x05, 0x44, 0x56, 0x5c, 0x40, 0x3d, 0x34, 0xb5, 0x6b, 0xc2, 373 0x2e, 0xb5, 0x43, 0xc3, 0x3b, 0x0a, 0x04, 0x2a, 0x4c, 0x3f, 0x56, 0x3f, 374 0x53, 0x2a, 0x4a, 0x0a, 0x04, 0x2a, 0x4b, 0x39, 0x52, 0x39, 0x50, 0x2a, 375 0x4a, 0x0a, 0x04, 0x31, 0x42, 0x45, 0x4c, 0x3f, 0x53, 0x2a, 0x4a, 0x0a, 376 0x04, 0x3f, 0x49, 0x38, 0x50, 0x2a, 0x4a, 0x31, 0x43, 0x0a, 0x04, 0x3f, 377 0x36, 0x57, 0x3e, 0x49, 0x4b, 0x32, 0x40, 0x08, 0x02, 0x3c, 0x3b, 0x4d, 378 0x43, 0x00, 0x02, 0x3b, 0x3b, 0x31, 0x36, 0x43, 0x3f, 0x48, 0x3d, 0x3f, 379 0x36, 0xc4, 0x82, 0xbf, 0xc7, 0x00, 0x02, 0x3e, 0x3c, 0xbc, 0x58, 0xbd, 380 0x93, 0x47, 0x3e, 0x45, 0x44, 0x3d, 0x43, 0x4d, 0x45, 0x02, 0x04, 0x39, 381 0x3b, 0x39, 0x3d, 0x39, 0x39, 0x3c, 0x38, 0x3b, 0x38, 0x3e, 0x38, 0x3e, 382 0x3a, 0x3f, 0x3a, 0x41, 0x37, 0x3c, 0x3d, 0x3c, 0x42, 0x3c, 0x40, 0x02, 383 0x04, 0x46, 0x3c, 0x46, 0x3e, 0x46, 0x3a, 0x48, 0x3a, 0x46, 0x3a, 0x4a, 384 0x3a, 0x4a, 0x3c, 0x4a, 0x3a, 0x4a, 0x3e, 0x48, 0x3e, 0x4a, 0x3e, 0x46, 385 0x3e, 0x0a, 0x04, 0x45, 0x42, 0x42, 0x45, 0x45, 0x47, 0x48, 0x44, 0x0a, 386 0x03, 0x4e, 0x43, 0x4d, 0x3f, 0x48, 0x44, 0x0a, 0x04, 0x32, 0x4b, 0x36, 387 0x48, 0x32, 0x46, 0x2e, 0x4a, 0x0d, 0x0a, 0x01, 0x01, 0x00, 0x20, 0x1e, 388 0x20, 0x0a, 0x00, 0x01, 0x01, 0x30, 0x1e, 0x20, 0x01, 0x17, 0x84, 0x00, 389 0x04, 0x0a, 0x02, 0x01, 0x02, 0x20, 0x1e, 0x20, 0x0a, 0x05, 0x01, 0x03, 390 0x20, 0x1e, 0x20, 0x0a, 0x06, 0x01, 0x04, 0x20, 0x1e, 0x20, 0x0a, 0x03, 391 0x01, 0x05, 0x20, 0x1e, 0x20, 0x0a, 0x07, 0x01, 0x07, 0x20, 0x1e, 0x20, 392 0x0a, 0x08, 0x01, 0x06, 0x20, 0x1e, 0x20, 0x0a, 0x09, 0x01, 0x08, 0x20, 393 0x1e, 0x20, 0x0a, 0x0a, 0x01, 0x09, 0x20, 0x1e, 0x20, 0x0a, 0x0c, 0x03, 394 0x0a, 0x0b, 0x0c, 0x1a, 0x40, 0x1d, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 395 0x00, 0x3f, 0x9d, 0xc9, 0xc2, 0x91, 0x98, 0x43, 0x6d, 0xc2, 0x20, 0xff, 396 0x01, 0x17, 0x81, 0x00, 0x04, 0x0a, 0x0c, 0x04, 0x0d, 0x0e, 0x0f, 0x10, 397 0x0a, 0x3f, 0xff, 0xbd, 0x34, 0xaf, 0xbc, 0xb4, 0xe0, 0x2c, 0x3f, 0xbc, 398 0x62, 0x3e, 0x74, 0x62, 0x41, 0xfe, 0xe7, 0x20, 0xff, 0x0a, 0x02, 0x01, 399 0x11, 0x20, 0x1e, 0x20 400 }; 401 402 403 static const uint8 kFloppyIcon[] = { 404 0x6e, 0x63, 0x69, 0x66, 0x0d, 0x03, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 405 0x00, 0x6a, 0x02, 0x00, 0x16, 0x02, 0x38, 0x6a, 0xad, 0x38, 0xeb, 0x7a, 406 0xbb, 0x77, 0x73, 0x3a, 0xde, 0x88, 0x48, 0xce, 0xdc, 0x4a, 0x75, 0xed, 407 0x00, 0x7a, 0xff, 0x4b, 0x02, 0x00, 0x16, 0x02, 0x38, 0x6a, 0xad, 0x38, 408 0xeb, 0x7a, 0xbb, 0x77, 0x73, 0x3a, 0xde, 0x88, 0x48, 0xce, 0xdc, 0x4a, 409 0x75, 0xed, 0x00, 0x8a, 0xff, 0x2c, 0x05, 0x7d, 0x02, 0x00, 0x16, 0x02, 410 0x39, 0xc6, 0x30, 0x36, 0xa8, 0x1b, 0xb9, 0x51, 0xe6, 0x3c, 0x5b, 0xb3, 411 0x4b, 0x4d, 0xa8, 0x4a, 0x1a, 0xa1, 0x00, 0x3a, 0xff, 0x5d, 0x02, 0x00, 412 0x16, 0x02, 0xb7, 0x16, 0xa4, 0xba, 0x87, 0xfe, 0x3c, 0xb2, 0x07, 0xb9, 413 0x49, 0xed, 0x48, 0x87, 0xd8, 0x4a, 0x1e, 0x62, 0x01, 0x75, 0xfe, 0xc4, 414 0x02, 0x00, 0x16, 0x02, 0xb7, 0x16, 0xa4, 0xba, 0x87, 0xfe, 0x3c, 0xb2, 415 0x07, 0xb9, 0x49, 0xed, 0x48, 0x87, 0xd8, 0x4a, 0x1e, 0x62, 0x00, 0x5c, 416 0xfe, 0x9b, 0x02, 0x00, 0x16, 0x05, 0x36, 0xef, 0x60, 0x38, 0xe2, 0xe5, 417 0xbd, 0x22, 0x41, 0x3b, 0x2f, 0xce, 0x4a, 0x0e, 0x78, 0x4a, 0x5a, 0x6c, 418 0x00, 0xb8, 0x38, 0xe6, 0x77, 0xb8, 0xbd, 0xd2, 0xff, 0x93, 0x02, 0x00, 419 0x16, 0x05, 0x34, 0x0a, 0x8f, 0x38, 0xd2, 0xa2, 0xba, 0xb4, 0xc5, 0x35, 420 0xe9, 0xec, 0x49, 0xfd, 0x24, 0x4a, 0x64, 0x62, 0x00, 0xe1, 0x38, 0xff, 421 0x75, 0xd7, 0xba, 0xf3, 0xfd, 0xd0, 0x02, 0x00, 0x16, 0x02, 0x36, 0x67, 422 0xbe, 0x39, 0xdd, 0xbc, 0xbe, 0x50, 0x04, 0x3a, 0xe0, 0x9f, 0x4b, 0x85, 423 0x01, 0x49, 0x2a, 0x3f, 0x00, 0xff, 0xff, 0xd8, 0x03, 0x38, 0x6d, 0xbe, 424 0x02, 0x00, 0x16, 0x02, 0x3c, 0x40, 0xef, 0x3b, 0x82, 0xd1, 0xba, 0xeb, 425 0x42, 0x3b, 0xbf, 0x4d, 0x4a, 0xa7, 0xce, 0x49, 0x5d, 0xc1, 0xff, 0x01, 426 0x00, 0x4a, 0x12, 0x0a, 0x05, 0x44, 0x5a, 0x44, 0x40, 0x5e, 0x40, 0x5f, 427 0x45, 0x49, 0x5a, 0x0a, 0x06, 0x45, 0x58, 0x5c, 0x42, 0x5c, 0x40, 0x3d, 428 0x34, 0xb5, 0x6b, 0xc2, 0x2e, 0xb5, 0x63, 0xc3, 0xbb, 0x0a, 0x04, 0x44, 429 0x58, 0x26, 0x4a, 0x26, 0x47, 0x44, 0x54, 0x0a, 0x04, 0x44, 0x59, 0x5c, 430 0x42, 0x5c, 0x3e, 0x44, 0x54, 0x0a, 0x05, 0x44, 0x56, 0x5c, 0x40, 0x3d, 431 0x34, 0xb5, 0x6b, 0xc2, 0x2e, 0xb5, 0x43, 0xc3, 0x3b, 0x0a, 0x04, 0x2a, 432 0x4c, 0x3f, 0x56, 0x3f, 0x53, 0x2a, 0x4a, 0x0a, 0x04, 0x2a, 0x4b, 0x39, 433 0x52, 0x39, 0x50, 0x2a, 0x4a, 0x0a, 0x04, 0x31, 0x42, 0x45, 0x4c, 0x3f, 434 0x53, 0x2a, 0x4a, 0x0a, 0x04, 0x3f, 0x49, 0x38, 0x50, 0x2a, 0x4a, 0x31, 435 0x43, 0x0a, 0x04, 0x3f, 0x36, 0x57, 0x3e, 0x49, 0x4b, 0x32, 0x40, 0x08, 436 0x02, 0x3c, 0x3b, 0x4d, 0x43, 0x00, 0x02, 0x3b, 0x3b, 0x31, 0x36, 0x43, 437 0x3f, 0x48, 0x3d, 0x3f, 0x36, 0xc4, 0x82, 0xbf, 0xc7, 0x00, 0x02, 0x3e, 438 0x3c, 0xbc, 0x58, 0xbd, 0x93, 0x47, 0x3e, 0x45, 0x44, 0x3d, 0x43, 0x4d, 439 0x45, 0x02, 0x04, 0x39, 0x3b, 0x39, 0x3d, 0x39, 0x39, 0x3c, 0x38, 0x3b, 440 0x38, 0x3e, 0x38, 0x3e, 0x3a, 0x3f, 0x3a, 0x41, 0x37, 0x3c, 0x3d, 0x3c, 441 0x42, 0x3c, 0x40, 0x02, 0x04, 0x46, 0x3c, 0x46, 0x3e, 0x46, 0x3a, 0x48, 442 0x3a, 0x46, 0x3a, 0x4a, 0x3a, 0x4a, 0x3c, 0x4a, 0x3a, 0x4a, 0x3e, 0x48, 443 0x3e, 0x4a, 0x3e, 0x46, 0x3e, 0x0a, 0x04, 0x45, 0x42, 0x42, 0x45, 0x45, 444 0x47, 0x48, 0x44, 0x0a, 0x03, 0x4e, 0x43, 0x4d, 0x3f, 0x48, 0x44, 0x0a, 445 0x04, 0x32, 0x4b, 0x36, 0x48, 0x32, 0x46, 0x2e, 0x4a, 0x0d, 0x0a, 0x01, 446 0x01, 0x00, 0x20, 0x1e, 0x20, 0x0a, 0x00, 0x01, 0x01, 0x30, 0x1e, 0x20, 447 0x01, 0x17, 0x84, 0x00, 0x04, 0x0a, 0x02, 0x01, 0x02, 0x20, 0x1e, 0x20, 448 0x0a, 0x05, 0x01, 0x03, 0x20, 0x1e, 0x20, 0x0a, 0x06, 0x01, 0x04, 0x20, 449 0x1e, 0x20, 0x0a, 0x03, 0x01, 0x05, 0x20, 0x1e, 0x20, 0x0a, 0x07, 0x01, 450 0x07, 0x20, 0x1e, 0x20, 0x0a, 0x08, 0x01, 0x06, 0x20, 0x1e, 0x20, 0x0a, 451 0x09, 0x01, 0x08, 0x20, 0x1e, 0x20, 0x0a, 0x0a, 0x01, 0x09, 0x20, 0x1e, 452 0x20, 0x0a, 0x0c, 0x03, 0x0a, 0x0b, 0x0c, 0x1a, 0x40, 0x1d, 0x05, 0x00, 453 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x9d, 0xc9, 0xc2, 0x91, 0x98, 0x43, 454 0x6d, 0xc2, 0x20, 0xff, 0x01, 0x17, 0x81, 0x00, 0x04, 0x0a, 0x0c, 0x04, 455 0x0d, 0x0e, 0x0f, 0x10, 0x0a, 0x3f, 0xff, 0xbd, 0x34, 0xaf, 0xbc, 0xb4, 456 0xe0, 0x2c, 0x3f, 0xbc, 0x62, 0x3e, 0x74, 0x62, 0x41, 0xfe, 0xe7, 0x20, 457 0xff, 0x0a, 0x02, 0x01, 0x11, 0x20, 0x1e, 0x20 458 }; 459 460 device_icon kKeyIconData = { (int32)sizeof(kDeviceIcon), (void *)kDeviceIcon }; 461 device_icon kCDIconData = { (int32)sizeof(kCDIcon), (void *)kCDIcon }; 462 device_icon kMSIconData = { (int32)sizeof(kMemoryStickIcon), 463 (void *)kMemoryStickIcon }; 464 device_icon kSDIconData = { (int32)sizeof(kSDIcon), (void *)kSDIcon }; 465 device_icon kMobileIconData = { (int32)sizeof(kMobileIcon), 466 (void *)kMobileIcon }; 467 device_icon kFloppyIconData = { (int32)sizeof(kFloppyIcon), 468 (void *)kFloppyIcon }; 469 470 471 struct { 472 const char *vendor; 473 const char *product; 474 device_icon *icon; 475 const char *name; 476 } kIconMatches[] = { 477 // matches for Hama USB 2.0 Card Reader 35 in 1 478 // vendor: "Transcend Information, Inc." 479 // product: "63-in-1 Multi-Card Reader/Writer" ver. 0100 480 // which report things like "Generic " "USB CF Reader " 481 // { NULL, " CF Reader", &kCFIconData, "devices/drive-removable-media-flash" }, 482 { NULL, " SD Reader", &kSDIconData, "devices/drive-removable-media-flash" }, 483 { NULL, " MS Reader", &kMSIconData, "devices/drive-removable-media-flash" }, 484 // { NULL, " SM Reader", &kSMIconData, "devices/drive-removable-media-flash" }, 485 // match for my Kazam mobile phone 486 // stupid thing says "MEDIATEK" " FLASH DISK " even for internal memory 487 { "MEDIATEK", NULL, &kMobileIconData, 488 "devices/drive-removable-media-flash" }, 489 { NULL, NULL, NULL, NULL } 490 }; 491 492 493 // 494 //#pragma mark - Forward Declarations 495 // 496 497 498 static void usb_disk_callback(void *cookie, status_t status, void *data, 499 size_t actualLength); 500 501 status_t usb_disk_mass_storage_reset(disk_device *device); 502 uint8 usb_disk_get_max_lun(disk_device *device); 503 void usb_disk_reset_recovery(disk_device *device); 504 status_t usb_disk_transfer_data(disk_device *device, bool directionIn, 505 void *data, size_t dataLength); 506 status_t usb_disk_receive_csw(disk_device *device, 507 usb_massbulk_command_status_wrapper *status); 508 status_t usb_disk_operation(device_lun *lun, uint8* operation, 509 size_t opLength, void *data, size_t *dataLength, 510 bool directionIn, err_act *action = NULL); 511 512 status_t usb_disk_send_diagnostic(device_lun *lun); 513 status_t usb_disk_request_sense(device_lun *lun, err_act *action); 514 status_t usb_disk_mode_sense(device_lun *lun); 515 status_t usb_disk_test_unit_ready(device_lun *lun, err_act *action = NULL); 516 status_t usb_disk_inquiry(device_lun *lun); 517 status_t usb_disk_reset_capacity(device_lun *lun); 518 status_t usb_disk_update_capacity(device_lun *lun); 519 status_t usb_disk_synchronize(device_lun *lun, bool force); 520 521 522 // 523 //#pragma mark - Device Allocation Helper Functions 524 // 525 526 527 void 528 usb_disk_free_device_and_luns(disk_device *device) 529 { 530 mutex_lock(&device->lock); 531 mutex_destroy(&device->lock); 532 delete_sem(device->notify); 533 delete_sem(device->interruptLock); 534 for (uint8 i = 0; i < device->lun_count; i++) 535 free(device->luns[i]); 536 free(device->luns); 537 free(device); 538 } 539 540 541 // 542 //#pragma mark - Bulk-only Mass Storage Functions 543 // 544 545 546 status_t 547 usb_disk_mass_storage_reset(disk_device *device) 548 { 549 return gUSBModule->send_request(device->device, USB_REQTYPE_INTERFACE_OUT 550 | USB_REQTYPE_CLASS, USB_MASSBULK_REQUEST_MASS_STORAGE_RESET, 0x0000, 551 device->interface, 0, NULL, NULL); 552 } 553 554 555 uint8 556 usb_disk_get_max_lun(disk_device *device) 557 { 558 uint8 result = 0; 559 size_t actualLength = 0; 560 561 // devices that do not support multiple LUNs may stall this request 562 if (gUSBModule->send_request(device->device, USB_REQTYPE_INTERFACE_IN 563 | USB_REQTYPE_CLASS, USB_MASSBULK_REQUEST_GET_MAX_LUN, 0x0000, 564 device->interface, 1, &result, &actualLength) != B_OK 565 || actualLength != 1) { 566 return 0; 567 } 568 569 if (result > MAX_LOGICAL_UNIT_NUMBER) { 570 // invalid max lun 571 return 0; 572 } 573 574 return result; 575 } 576 577 578 void 579 usb_disk_reset_recovery(disk_device *device) 580 { 581 usb_disk_mass_storage_reset(device); 582 gUSBModule->clear_feature(device->bulk_in, USB_FEATURE_ENDPOINT_HALT); 583 gUSBModule->clear_feature(device->bulk_out, USB_FEATURE_ENDPOINT_HALT); 584 if (device->is_ufi) 585 gUSBModule->clear_feature(device->interrupt, USB_FEATURE_ENDPOINT_HALT); 586 } 587 588 589 status_t 590 usb_disk_transfer_data(disk_device *device, bool directionIn, void *data, 591 size_t dataLength) 592 { 593 status_t result = gUSBModule->queue_bulk(directionIn ? device->bulk_in 594 : device->bulk_out, data, dataLength, usb_disk_callback, device); 595 if (result != B_OK) { 596 TRACE_ALWAYS("failed to queue data transfer: %s\n", strerror(result)); 597 return result; 598 } 599 600 do { 601 result = acquire_sem_etc(device->notify, 1, B_RELATIVE_TIMEOUT, 602 10 * 1000 * 1000); 603 if (result == B_TIMED_OUT) { 604 // Cancel the transfer and collect the sem that should now be 605 // released through the callback on cancel. Handling of device 606 // reset is done in usb_disk_operation() when it detects that 607 // the transfer failed. 608 gUSBModule->cancel_queued_transfers(directionIn ? device->bulk_in 609 : device->bulk_out); 610 acquire_sem_etc(device->notify, 1, B_RELATIVE_TIMEOUT, 0); 611 } 612 } while (result == B_INTERRUPTED); 613 614 if (result != B_OK) { 615 TRACE_ALWAYS("acquire_sem failed while waiting for data transfer: %s\n", 616 strerror(result)); 617 return result; 618 } 619 620 return B_OK; 621 } 622 623 624 void 625 usb_disk_interrupt(void* cookie, int32 status, void* data, size_t length) 626 { 627 disk_device* device = (disk_device*)cookie; 628 // We release the lock even if the interrupt is invalid. This way there 629 // is at least a chance for the driver to terminate properly. 630 release_sem(device->interruptLock); 631 632 if (length != 2) { 633 TRACE_ALWAYS("interrupt of length %" B_PRIuSIZE "! (expected 2)\n", 634 length); 635 // In this case we do not reschedule the interrupt. This means the 636 // driver will be locked. The interrupt should perhaps be scheduled 637 // when starting a transfer instead. But getting there means something 638 // is really broken, so... 639 return; 640 } 641 642 // Reschedule the interrupt for next time 643 gUSBModule->queue_interrupt(device->interrupt, device->interruptBuffer, 2, 644 usb_disk_interrupt, cookie); 645 } 646 647 648 status_t 649 usb_disk_receive_csw_interrupt(disk_device *device, 650 interrupt_status_wrapper *status) 651 { 652 TRACE("Waiting for result...\n"); 653 gUSBModule->queue_interrupt(device->interrupt, 654 device->interruptBuffer, 2, usb_disk_interrupt, device); 655 656 acquire_sem(device->interruptLock); 657 658 status->status = device->interruptBuffer[0]; 659 status->misc = device->interruptBuffer[1]; 660 661 return B_OK; 662 } 663 664 status_t 665 usb_disk_receive_csw_bulk(disk_device *device, 666 usb_massbulk_command_status_wrapper *status) 667 { 668 status_t result = usb_disk_transfer_data(device, true, status, 669 sizeof(usb_massbulk_command_status_wrapper)); 670 if (result != B_OK) 671 return result; 672 673 if (device->status != B_OK 674 || device->actual_length 675 != sizeof(usb_massbulk_command_status_wrapper)) { 676 // receiving the command status wrapper failed 677 return B_ERROR; 678 } 679 680 return B_OK; 681 } 682 683 684 status_t 685 usb_disk_operation_interrupt(device_lun *lun, uint8* operation, 686 void *data, size_t *dataLength, bool directionIn, err_act *_action) 687 { 688 TRACE("operation: lun: %u; op: 0x%x; data: %p; dlen: %p (%lu); in: %c\n", 689 lun->logical_unit_number, operation[0], data, dataLength, 690 dataLength ? *dataLength : 0, directionIn ? 'y' : 'n'); 691 692 disk_device* device = lun->device; 693 694 // Step 1 : send the SCSI operation as a class specific request 695 size_t actualLength = 12; 696 status_t result = gUSBModule->send_request(device->device, 697 USB_REQTYPE_CLASS | USB_REQTYPE_INTERFACE_OUT, 0 /*request*/, 698 0/*value*/, device->interface/*index*/, 12, operation, &actualLength); 699 700 if (result != B_OK || actualLength != 12) { 701 TRACE("Command stage: wrote %ld bytes (error: %s)\n", 702 actualLength, strerror(result)); 703 704 // There was an error, we have to do a request sense to reset the device 705 if (operation[0] != SCSI_REQUEST_SENSE_6) { 706 usb_disk_request_sense(lun, _action); 707 } 708 return result; 709 } 710 711 // Step 2 : data phase : send or receive data 712 size_t transferedData = 0; 713 if (data != NULL && dataLength != NULL && *dataLength > 0) { 714 // we have data to transfer in a data stage 715 result = usb_disk_transfer_data(device, directionIn, data, *dataLength); 716 if (result != B_OK) { 717 TRACE("Error %s in data phase\n", strerror(result)); 718 return result; 719 } 720 721 transferedData = device->actual_length; 722 if (device->status != B_OK || transferedData != *dataLength) { 723 // sending or receiving of the data failed 724 if (device->status == B_DEV_STALLED) { 725 TRACE("stall while transfering data\n"); 726 gUSBModule->clear_feature(directionIn ? device->bulk_in 727 : device->bulk_out, USB_FEATURE_ENDPOINT_HALT); 728 } else { 729 TRACE_ALWAYS("sending or receiving of the data failed\n"); 730 usb_disk_reset_recovery(device); 731 return B_ERROR; 732 } 733 } 734 } 735 736 // step 3 : wait for the device to send the interrupt ACK 737 if (operation[0] != SCSI_REQUEST_SENSE_6) { 738 interrupt_status_wrapper status; 739 result = usb_disk_receive_csw_interrupt(device, &status); 740 if (result != B_OK) { 741 // in case of a stall or error clear the stall and try again 742 TRACE("Error receiving interrupt: %s. Retrying...\n", 743 strerror(result)); 744 gUSBModule->clear_feature(device->bulk_in, 745 USB_FEATURE_ENDPOINT_HALT); 746 result = usb_disk_receive_csw_interrupt(device, &status); 747 } 748 749 if (result != B_OK) { 750 TRACE_ALWAYS("receiving the command status interrupt failed\n"); 751 usb_disk_reset_recovery(device); 752 return result; 753 } 754 755 // wait for the device to finish the operation. 756 result = usb_disk_request_sense(lun, _action); 757 } 758 return result; 759 } 760 761 762 status_t 763 usb_disk_operation_bulk(device_lun *lun, uint8* operation, 764 size_t operationLength, void *data, size_t *dataLength, bool directionIn, 765 err_act *_action) 766 { 767 TRACE("operation: lun: %u; op: %u; data: %p; dlen: %p (%lu); in: %c\n", 768 lun->logical_unit_number, operation[0], 769 data, dataLength, dataLength ? *dataLength : 0, 770 directionIn ? 'y' : 'n'); 771 772 disk_device *device = lun->device; 773 usb_massbulk_command_block_wrapper command; 774 command.signature = USB_MASSBULK_CBW_SIGNATURE; 775 command.tag = device->current_tag++; 776 command.data_transfer_length = (dataLength != NULL ? *dataLength : 0); 777 command.flags = (directionIn ? USB_MASSBULK_CBW_DATA_INPUT 778 : USB_MASSBULK_CBW_DATA_OUTPUT); 779 command.lun = lun->logical_unit_number; 780 command.command_block_length 781 = device->is_atapi ? ATAPI_COMMAND_LENGTH : operationLength; 782 memset(command.command_block, 0, sizeof(command.command_block)); 783 memcpy(command.command_block, operation, operationLength); 784 785 status_t result = usb_disk_transfer_data(device, false, &command, 786 sizeof(usb_massbulk_command_block_wrapper)); 787 if (result != B_OK) 788 return result; 789 790 if (device->status != B_OK || 791 device->actual_length != sizeof(usb_massbulk_command_block_wrapper)) { 792 // sending the command block wrapper failed 793 TRACE_ALWAYS("sending the command block wrapper failed: %s\n", 794 strerror(device->status)); 795 usb_disk_reset_recovery(device); 796 return B_ERROR; 797 } 798 799 size_t transferedData = 0; 800 if (data != NULL && dataLength != NULL && *dataLength > 0) { 801 // we have data to transfer in a data stage 802 result = usb_disk_transfer_data(device, directionIn, data, 803 *dataLength); 804 if (result != B_OK) 805 return result; 806 807 transferedData = device->actual_length; 808 if (device->status != B_OK || transferedData != *dataLength) { 809 // sending or receiving of the data failed 810 if (device->status == B_DEV_STALLED) { 811 TRACE("stall while transfering data\n"); 812 gUSBModule->clear_feature(directionIn ? device->bulk_in 813 : device->bulk_out, USB_FEATURE_ENDPOINT_HALT); 814 } else { 815 TRACE_ALWAYS("sending or receiving of the data failed: %s\n", 816 strerror(device->status)); 817 usb_disk_reset_recovery(device); 818 return B_ERROR; 819 } 820 } 821 } 822 823 usb_massbulk_command_status_wrapper status; 824 result = usb_disk_receive_csw_bulk(device, &status); 825 if (result != B_OK) { 826 // in case of a stall or error clear the stall and try again 827 gUSBModule->clear_feature(device->bulk_in, USB_FEATURE_ENDPOINT_HALT); 828 result = usb_disk_receive_csw_bulk(device, &status); 829 } 830 831 if (result != B_OK) { 832 TRACE_ALWAYS("receiving the command status wrapper failed: %s\n", 833 strerror(result)); 834 usb_disk_reset_recovery(device); 835 return result; 836 } 837 838 if (status.signature != USB_MASSBULK_CSW_SIGNATURE 839 || status.tag != command.tag) { 840 // the command status wrapper is not valid 841 TRACE_ALWAYS("command status wrapper is not valid: %#" B_PRIx32 "\n", 842 status.signature); 843 usb_disk_reset_recovery(device); 844 return B_ERROR; 845 } 846 847 switch (status.status) { 848 case USB_MASSBULK_CSW_STATUS_COMMAND_PASSED: 849 case USB_MASSBULK_CSW_STATUS_COMMAND_FAILED: 850 { 851 // The residue from "status.data_residue" is not maintained 852 // correctly by some devices, so calculate it instead. 853 uint32 residue = command.data_transfer_length - transferedData; 854 855 if (dataLength != NULL) { 856 *dataLength -= residue; 857 if (transferedData < *dataLength) { 858 TRACE_ALWAYS("less data transfered than indicated: %" 859 B_PRIuSIZE " vs. %" B_PRIuSIZE "\n", transferedData, 860 *dataLength); 861 *dataLength = transferedData; 862 } 863 } 864 865 if (status.status == USB_MASSBULK_CSW_STATUS_COMMAND_PASSED) { 866 // the operation is complete and has succeeded 867 return B_OK; 868 } else { 869 if (operation[0] == SCSI_REQUEST_SENSE_6) 870 return B_ERROR; 871 872 // the operation is complete but has failed at the SCSI level 873 if (operation[0] != SCSI_TEST_UNIT_READY_6) { 874 TRACE_ALWAYS("operation %#" B_PRIx8 875 " failed at the SCSI level\n", operation[0]); 876 } 877 878 result = usb_disk_request_sense(lun, _action); 879 return result == B_OK ? B_ERROR : result; 880 } 881 } 882 883 case USB_MASSBULK_CSW_STATUS_PHASE_ERROR: 884 { 885 // a protocol or device error occured 886 TRACE_ALWAYS("phase error in operation %#" B_PRIx8 "\n", 887 operation[0]); 888 usb_disk_reset_recovery(device); 889 return B_ERROR; 890 } 891 892 default: 893 { 894 // command status wrapper is not meaningful 895 TRACE_ALWAYS("command status wrapper has invalid status\n"); 896 usb_disk_reset_recovery(device); 897 return B_ERROR; 898 } 899 } 900 } 901 902 903 status_t 904 usb_disk_operation(device_lun *lun, uint8* operation, size_t opLength, 905 void *data, size_t *dataLength, bool directionIn, err_act *_action) 906 { 907 if (lun->device->is_ufi) { 908 return usb_disk_operation_interrupt(lun, operation, data, dataLength, 909 directionIn, _action); 910 } else { 911 return usb_disk_operation_bulk(lun, operation, opLength, 912 data, dataLength, directionIn, _action); 913 } 914 } 915 916 917 // 918 //#pragma mark - Helper/Convenience Functions 919 // 920 921 922 status_t 923 usb_disk_send_diagnostic(device_lun *lun) 924 { 925 uint8 commandBlock[12]; 926 memset(commandBlock, 0, sizeof(commandBlock)); 927 928 commandBlock[0] = SCSI_SEND_DIAGNOSTIC; 929 commandBlock[1] = (lun->logical_unit_number << 5) | 4; 930 931 status_t result = usb_disk_operation(lun, commandBlock, 6, NULL, 932 NULL, false); 933 934 int retry = 100; 935 err_act action = err_act_ok; 936 while(result == B_DEV_NO_MEDIA && retry > 0) { 937 snooze(10000); 938 result = usb_disk_request_sense(lun, &action); 939 retry--; 940 } 941 942 if (result != B_OK) 943 TRACE("Send Diagnostic failed: %s\n", strerror(result)); 944 return result; 945 } 946 947 948 status_t 949 usb_disk_request_sense(device_lun *lun, err_act *_action) 950 { 951 size_t dataLength = sizeof(scsi_request_sense_6_parameter); 952 uint8 commandBlock[12]; 953 memset(commandBlock, 0, sizeof(commandBlock)); 954 955 commandBlock[0] = SCSI_REQUEST_SENSE_6; 956 commandBlock[1] = lun->logical_unit_number << 5; 957 commandBlock[2] = 0; // page code 958 commandBlock[4] = dataLength; 959 960 scsi_request_sense_6_parameter parameter; 961 status_t result = B_ERROR; 962 for (uint32 tries = 0; tries < 3; tries++) { 963 result = usb_disk_operation(lun, commandBlock, 6, ¶meter, 964 &dataLength, true); 965 if (result != B_TIMED_OUT) 966 break; 967 snooze(100000); 968 } 969 if (result != B_OK) { 970 TRACE_ALWAYS("getting request sense data failed: %s\n", 971 strerror(result)); 972 return result; 973 } 974 975 const char *label = NULL; 976 err_act action = err_act_fail; 977 status_t status = B_ERROR; 978 scsi_get_sense_asc_info((parameter.additional_sense_code << 8) 979 | parameter.additional_sense_code_qualifier, &label, &action, 980 &status); 981 982 if (parameter.sense_key > SCSI_SENSE_KEY_NOT_READY 983 && parameter.sense_key != SCSI_SENSE_KEY_UNIT_ATTENTION) { 984 TRACE_ALWAYS("request_sense: key: 0x%02x; asc: 0x%02x; ascq: " 985 "0x%02x; %s\n", parameter.sense_key, 986 parameter.additional_sense_code, 987 parameter.additional_sense_code_qualifier, 988 label ? label : "(unknown)"); 989 } 990 991 if ((parameter.additional_sense_code == 0 992 && parameter.additional_sense_code_qualifier == 0) 993 || label == NULL) { 994 scsi_get_sense_key_info(parameter.sense_key, &label, &action, &status); 995 } 996 997 if (status == B_DEV_MEDIA_CHANGED) { 998 lun->media_changed = true; 999 lun->media_present = true; 1000 } else if (parameter.sense_key == SCSI_SENSE_KEY_UNIT_ATTENTION 1001 && status != B_DEV_NO_MEDIA) { 1002 lun->media_present = true; 1003 } else if (status == B_DEV_NOT_READY) { 1004 lun->media_present = false; 1005 usb_disk_reset_capacity(lun); 1006 } 1007 1008 if (_action != NULL) 1009 *_action = action; 1010 1011 return status; 1012 } 1013 1014 1015 status_t 1016 usb_disk_mode_sense(device_lun *lun) 1017 { 1018 size_t dataLength = sizeof(scsi_mode_sense_6_parameter); 1019 1020 uint8 commandBlock[12]; 1021 memset(commandBlock, 0, sizeof(commandBlock)); 1022 1023 commandBlock[0] = SCSI_MODE_SENSE_6; 1024 commandBlock[1] = SCSI_MODE_PAGE_DEVICE_CONFIGURATION; 1025 commandBlock[2] = 0; // Current values 1026 commandBlock[3] = dataLength >> 8; 1027 commandBlock[4] = dataLength; 1028 1029 scsi_mode_sense_6_parameter parameter; 1030 status_t result = usb_disk_operation(lun, commandBlock, 6, 1031 ¶meter, &dataLength, true); 1032 if (result != B_OK) { 1033 TRACE_ALWAYS("getting mode sense data failed: %s\n", strerror(result)); 1034 return result; 1035 } 1036 1037 lun->write_protected 1038 = (parameter.device_specific & SCSI_DEVICE_SPECIFIC_WRITE_PROTECT) 1039 != 0; 1040 TRACE_ALWAYS("write protected: %s\n", lun->write_protected ? "yes" : "no"); 1041 return B_OK; 1042 } 1043 1044 1045 status_t 1046 usb_disk_test_unit_ready(device_lun *lun, err_act *_action) 1047 { 1048 // if unsupported we assume the unit is fixed and therefore always ok 1049 if (lun->device->is_ufi || !lun->device->tur_supported) 1050 return B_OK; 1051 1052 status_t result = B_OK; 1053 uint8 commandBlock[12]; 1054 memset(commandBlock, 0, sizeof(commandBlock)); 1055 1056 if (lun->device->is_atapi) { 1057 commandBlock[0] = SCSI_START_STOP_UNIT_6; 1058 commandBlock[1] = lun->logical_unit_number << 5; 1059 commandBlock[2] = 0; 1060 commandBlock[3] = 0; 1061 commandBlock[4] = 1; 1062 1063 result = usb_disk_operation(lun, commandBlock, 6, NULL, NULL, false, 1064 _action); 1065 } else { 1066 commandBlock[0] = SCSI_TEST_UNIT_READY_6; 1067 commandBlock[1] = lun->logical_unit_number << 5; 1068 commandBlock[2] = 0; 1069 commandBlock[3] = 0; 1070 commandBlock[4] = 0; 1071 result = usb_disk_operation(lun, commandBlock, 6, NULL, NULL, true, 1072 _action); 1073 } 1074 1075 if (result == B_DEV_INVALID_IOCTL) { 1076 lun->device->tur_supported = false; 1077 return B_OK; 1078 } 1079 1080 return result; 1081 } 1082 1083 1084 status_t 1085 usb_disk_inquiry(device_lun *lun) 1086 { 1087 size_t dataLength = sizeof(scsi_inquiry_6_parameter); 1088 1089 uint8 commandBlock[12]; 1090 memset(commandBlock, 0, sizeof(commandBlock)); 1091 1092 commandBlock[0] = SCSI_INQUIRY_6; 1093 commandBlock[1] = lun->logical_unit_number << 5; 1094 commandBlock[2] = 0; // page code 1095 commandBlock[4] = dataLength; 1096 1097 scsi_inquiry_6_parameter parameter; 1098 status_t result = B_ERROR; 1099 err_act action = err_act_ok; 1100 for (uint32 tries = 0; tries < 3; tries++) { 1101 result = usb_disk_operation(lun, commandBlock, 6, ¶meter, 1102 &dataLength, true, &action); 1103 if (result == B_OK || (action != err_act_retry 1104 && action != err_act_many_retries)) { 1105 break; 1106 } 1107 } 1108 if (result != B_OK) { 1109 TRACE_ALWAYS("getting inquiry data failed: %s\n", strerror(result)); 1110 lun->device_type = B_DISK; 1111 lun->removable = true; 1112 return result; 1113 } 1114 1115 TRACE("peripherial_device_type 0x%02x\n", 1116 parameter.peripherial_device_type); 1117 TRACE("peripherial_qualifier 0x%02x\n", 1118 parameter.peripherial_qualifier); 1119 TRACE("removable_medium %s\n", 1120 parameter.removable_medium ? "yes" : "no"); 1121 TRACE("version 0x%02x\n", parameter.version); 1122 TRACE("response_data_format 0x%02x\n", parameter.response_data_format); 1123 TRACE_ALWAYS("vendor_identification \"%.8s\"\n", 1124 parameter.vendor_identification); 1125 TRACE_ALWAYS("product_identification \"%.16s\"\n", 1126 parameter.product_identification); 1127 TRACE_ALWAYS("product_revision_level \"%.4s\"\n", 1128 parameter.product_revision_level); 1129 1130 memcpy(lun->vendor_name, parameter.vendor_identification, 1131 MIN(sizeof(lun->vendor_name), sizeof(parameter.vendor_identification))); 1132 memcpy(lun->product_name, parameter.product_identification, 1133 MIN(sizeof(lun->product_name), 1134 sizeof(parameter.product_identification))); 1135 memcpy(lun->product_revision, parameter.product_revision_level, 1136 MIN(sizeof(lun->product_revision), 1137 sizeof(parameter.product_revision_level))); 1138 1139 lun->device_type = parameter.peripherial_device_type; /* 1:1 mapping */ 1140 lun->removable = (parameter.removable_medium == 1); 1141 return B_OK; 1142 } 1143 1144 1145 status_t 1146 usb_disk_reset_capacity(device_lun *lun) 1147 { 1148 lun->block_size = 512; 1149 lun->block_count = 0; 1150 return B_OK; 1151 } 1152 1153 1154 status_t 1155 usb_disk_update_capacity(device_lun *lun) 1156 { 1157 size_t dataLength = sizeof(scsi_read_capacity_10_parameter); 1158 scsi_read_capacity_10_parameter parameter; 1159 status_t result = B_ERROR; 1160 err_act action = err_act_ok; 1161 1162 uint8 commandBlock[12]; 1163 memset(commandBlock, 0, sizeof(commandBlock)); 1164 1165 commandBlock[0] = SCSI_READ_CAPACITY_10; 1166 commandBlock[1] = lun->logical_unit_number << 5; 1167 1168 // Retry reading the capacity up to three times. The first try might only 1169 // yield a unit attention telling us that the device or media status 1170 // changed, which is more or less expected if it is the first operation 1171 // on the device or the device only clears the unit atention for capacity 1172 // reads. 1173 for (int32 i = 0; i < 5; i++) { 1174 result = usb_disk_operation(lun, commandBlock, 10, ¶meter, 1175 &dataLength, true, &action); 1176 1177 if (result == B_OK || (action != err_act_retry 1178 && action != err_act_many_retries)) { 1179 break; 1180 } 1181 1182 // In some cases, it's best to wait a little for the device to settle 1183 // before retrying. 1184 if (lun->device->is_ufi && (result == B_DEV_NO_MEDIA 1185 || result == B_TIMED_OUT || result == B_DEV_STALLED)) 1186 snooze(10000); 1187 } 1188 1189 if (result != B_OK) { 1190 TRACE_ALWAYS("failed to update capacity: %s\n", strerror(result)); 1191 lun->media_present = false; 1192 lun->media_changed = false; 1193 usb_disk_reset_capacity(lun); 1194 return result; 1195 } 1196 1197 lun->media_present = true; 1198 lun->media_changed = false; 1199 lun->block_size = B_BENDIAN_TO_HOST_INT32(parameter.logical_block_length); 1200 lun->block_count = 1201 B_BENDIAN_TO_HOST_INT32(parameter.last_logical_block_address) + 1; 1202 return B_OK; 1203 } 1204 1205 1206 status_t 1207 usb_disk_synchronize(device_lun *lun, bool force) 1208 { 1209 if (lun->device->is_ufi) { 1210 // UFI use interrupt because it runs all commands immediately, and 1211 // tells us when its done. There is no cache involved in that case, 1212 // so nothing to synchronize. 1213 return B_UNSUPPORTED; 1214 } 1215 1216 if (lun->device->sync_support == 0) { 1217 // this device reported an illegal request when syncing or repeatedly 1218 // returned an other error, it apparently does not support syncing... 1219 return B_UNSUPPORTED; 1220 } 1221 1222 if (!lun->should_sync && !force) 1223 return B_OK; 1224 1225 uint8 commandBlock[12]; 1226 memset(commandBlock, 0, sizeof(commandBlock)); 1227 1228 commandBlock[0] = SCSI_SYNCHRONIZE_CACHE_10; 1229 commandBlock[1] = lun->logical_unit_number << 5; 1230 1231 status_t result = usb_disk_operation(lun, commandBlock, 10, 1232 NULL, NULL, false); 1233 1234 if (result == B_OK) { 1235 lun->device->sync_support = SYNC_SUPPORT_RELOAD; 1236 lun->should_sync = false; 1237 return B_OK; 1238 } 1239 1240 if (result == B_DEV_INVALID_IOCTL) 1241 lun->device->sync_support = 0; 1242 else 1243 lun->device->sync_support--; 1244 1245 return result; 1246 } 1247 1248 1249 // 1250 //#pragma mark - Device Attach/Detach Notifications and Callback 1251 // 1252 1253 1254 static void 1255 usb_disk_callback(void *cookie, status_t status, void *data, 1256 size_t actualLength) 1257 { 1258 //TRACE("callback()\n"); 1259 disk_device *device = (disk_device *)cookie; 1260 device->status = status; 1261 device->actual_length = actualLength; 1262 release_sem(device->notify); 1263 } 1264 1265 1266 static status_t 1267 usb_disk_device_added(usb_device newDevice, void **cookie) 1268 { 1269 TRACE("device_added(0x%08" B_PRIx32 ")\n", newDevice); 1270 disk_device *device = (disk_device *)malloc(sizeof(disk_device)); 1271 device->device = newDevice; 1272 device->removed = false; 1273 device->open_count = 0; 1274 device->interface = 0xff; 1275 device->current_tag = 0; 1276 device->sync_support = SYNC_SUPPORT_RELOAD; 1277 device->tur_supported = true; 1278 device->is_atapi = false; 1279 device->is_ufi = false; 1280 device->luns = NULL; 1281 1282 // scan through the interfaces to find our bulk-only data interface 1283 const usb_configuration_info *configuration 1284 = gUSBModule->get_configuration(newDevice); 1285 if (configuration == NULL) { 1286 free(device); 1287 return B_ERROR; 1288 } 1289 1290 for (size_t i = 0; i < configuration->interface_count; i++) { 1291 usb_interface_info *interface = configuration->interface[i].active; 1292 if (interface == NULL) 1293 continue; 1294 1295 if (interface->descr->interface_class == USB_MASS_STORAGE_DEVICE_CLASS 1296 && (((interface->descr->interface_subclass == 0x06 /* SCSI */ 1297 || interface->descr->interface_subclass == 0x02 /* ATAPI */ 1298 || interface->descr->interface_subclass == 0x05 /* ATAPI */) 1299 && interface->descr->interface_protocol == 0x50 /* bulk-only */) 1300 || (interface->descr->interface_subclass == 0x04 /* UFI */ 1301 && interface->descr->interface_protocol == 0x00))) { 1302 1303 bool hasIn = false; 1304 bool hasOut = false; 1305 bool hasInt = false; 1306 for (size_t j = 0; j < interface->endpoint_count; j++) { 1307 usb_endpoint_info *endpoint = &interface->endpoint[j]; 1308 if (endpoint == NULL) 1309 continue; 1310 1311 if (!hasIn && (endpoint->descr->endpoint_address 1312 & USB_ENDPOINT_ADDR_DIR_IN) != 0 1313 && endpoint->descr->attributes == USB_ENDPOINT_ATTR_BULK) { 1314 device->bulk_in = endpoint->handle; 1315 hasIn = true; 1316 } else if (!hasOut && (endpoint->descr->endpoint_address 1317 & USB_ENDPOINT_ADDR_DIR_IN) == 0 1318 && endpoint->descr->attributes == USB_ENDPOINT_ATTR_BULK) { 1319 device->bulk_out = endpoint->handle; 1320 hasOut = true; 1321 } else if (!hasInt && (endpoint->descr->endpoint_address 1322 & USB_ENDPOINT_ADDR_DIR_IN) 1323 && endpoint->descr->attributes 1324 == USB_ENDPOINT_ATTR_INTERRUPT) { 1325 device->interrupt = endpoint->handle; 1326 hasInt = true; 1327 } 1328 1329 if (hasIn && hasOut && hasInt) 1330 break; 1331 } 1332 1333 if (!(hasIn && hasOut)) { 1334 // Missing one of the required endpoints, try next interface 1335 continue; 1336 } 1337 1338 device->interface = interface->descr->interface_number; 1339 device->is_atapi = interface->descr->interface_subclass != 0x06 1340 && interface->descr->interface_subclass != 0x04; 1341 device->is_ufi = interface->descr->interface_subclass == 0x04; 1342 1343 if (device->is_ufi && !hasInt) { 1344 // UFI without interrupt endpoint is not possible. 1345 continue; 1346 } 1347 break; 1348 } 1349 } 1350 1351 if (device->interface == 0xff) { 1352 TRACE_ALWAYS("no valid bulk-only or CBI interface found\n"); 1353 free(device); 1354 return B_ERROR; 1355 } 1356 1357 mutex_init(&device->lock, "usb_disk device lock"); 1358 1359 device->notify = create_sem(0, "usb_disk callback notify"); 1360 if (device->notify < B_OK) { 1361 mutex_destroy(&device->lock); 1362 status_t result = device->notify; 1363 free(device); 1364 return result; 1365 } 1366 1367 if (device->is_ufi) { 1368 device->interruptLock = create_sem(0, "usb_disk interrupt lock"); 1369 if (device->interruptLock < B_OK) { 1370 mutex_destroy(&device->lock); 1371 delete_sem(device->notify); 1372 status_t result = device->interruptLock; 1373 free(device); 1374 return result; 1375 } 1376 } 1377 1378 device->lun_count = usb_disk_get_max_lun(device) + 1; 1379 device->luns = (device_lun **)malloc(device->lun_count 1380 * sizeof(device_lun *)); 1381 for (uint8 i = 0; i < device->lun_count; i++) 1382 device->luns[i] = NULL; 1383 1384 status_t result = B_OK; 1385 1386 TRACE_ALWAYS("device reports a lun count of %d\n", device->lun_count); 1387 for (uint8 i = 0; i < device->lun_count; i++) { 1388 // create the individual luns present on this device 1389 device_lun *lun = (device_lun *)malloc(sizeof(device_lun)); 1390 if (lun == NULL) { 1391 result = B_NO_MEMORY; 1392 break; 1393 } 1394 1395 device->luns[i] = lun; 1396 lun->device = device; 1397 lun->logical_unit_number = i; 1398 lun->should_sync = false; 1399 lun->media_present = true; 1400 lun->media_changed = true; 1401 1402 memset(lun->vendor_name, 0, sizeof(lun->vendor_name)); 1403 memset(lun->product_name, 0, sizeof(lun->product_name)); 1404 memset(lun->product_revision, 0, sizeof(lun->product_revision)); 1405 1406 usb_disk_reset_capacity(lun); 1407 1408 // initialize this lun 1409 result = usb_disk_inquiry(lun); 1410 1411 if (device->is_ufi) { 1412 // Reset the device 1413 // If we don't do it all the other commands except inquiry and send 1414 // diagnostics will be stalled. 1415 result = usb_disk_send_diagnostic(lun); 1416 } 1417 1418 err_act action = err_act_ok; 1419 for (uint32 tries = 0; tries < 8; tries++) { 1420 TRACE("usb lun %" B_PRIu8 " inquiry attempt %" B_PRIu32 " begin\n", 1421 i, tries); 1422 status_t ready = usb_disk_test_unit_ready(lun, &action); 1423 if (ready == B_OK || ready == B_DEV_NO_MEDIA 1424 || ready == B_DEV_MEDIA_CHANGED) { 1425 if (lun->device_type == B_CD) 1426 lun->write_protected = true; 1427 // TODO: check for write protection; disabled since some 1428 // devices lock up when getting the mode sense 1429 else if (/*usb_disk_mode_sense(lun) != B_OK*/true) 1430 lun->write_protected = false; 1431 1432 TRACE("usb lun %" B_PRIu8 " ready. write protected = %c%s\n", i, 1433 lun->write_protected ? 'y' : 'n', 1434 ready == B_DEV_NO_MEDIA ? " (no media inserted)" : ""); 1435 1436 break; 1437 } 1438 TRACE("usb lun %" B_PRIu8 " inquiry attempt %" B_PRIu32 " failed\n", 1439 i, tries); 1440 if (action != err_act_retry && action != err_act_many_retries) 1441 break; 1442 bigtime_t snoozeTime = 1000000 * tries; 1443 TRACE("snoozing %" B_PRIu64 " microseconds for usb lun\n", 1444 snoozeTime); 1445 snooze(snoozeTime); 1446 } 1447 1448 if (result != B_OK) 1449 break; 1450 } 1451 1452 if (result != B_OK) { 1453 TRACE_ALWAYS("failed to initialize logical units: %s\n", 1454 strerror(result)); 1455 usb_disk_free_device_and_luns(device); 1456 return result; 1457 } 1458 1459 mutex_lock(&gDeviceListLock); 1460 device->device_number = 0; 1461 disk_device *other = gDeviceList; 1462 while (other != NULL) { 1463 if (other->device_number >= device->device_number) 1464 device->device_number = other->device_number + 1; 1465 1466 other = (disk_device *)other->link; 1467 } 1468 1469 device->link = (void *)gDeviceList; 1470 gDeviceList = device; 1471 gLunCount += device->lun_count; 1472 for (uint8 i = 0; i < device->lun_count; i++) 1473 sprintf(device->luns[i]->name, DEVICE_NAME, device->device_number, i); 1474 mutex_unlock(&gDeviceListLock); 1475 1476 TRACE("new device: 0x%p\n", device); 1477 *cookie = (void *)device; 1478 return B_OK; 1479 } 1480 1481 1482 static status_t 1483 usb_disk_device_removed(void *cookie) 1484 { 1485 TRACE("device_removed(0x%p)\n", cookie); 1486 disk_device *device = (disk_device *)cookie; 1487 1488 mutex_lock(&gDeviceListLock); 1489 if (gDeviceList == device) { 1490 gDeviceList = (disk_device *)device->link; 1491 } else { 1492 disk_device *element = gDeviceList; 1493 while (element) { 1494 if (element->link == device) { 1495 element->link = device->link; 1496 break; 1497 } 1498 1499 element = (disk_device *)element->link; 1500 } 1501 } 1502 gLunCount -= device->lun_count; 1503 gDeviceCount--; 1504 1505 device->removed = true; 1506 gUSBModule->cancel_queued_transfers(device->bulk_in); 1507 gUSBModule->cancel_queued_transfers(device->bulk_out); 1508 if (device->open_count == 0) 1509 usb_disk_free_device_and_luns(device); 1510 1511 mutex_unlock(&gDeviceListLock); 1512 return B_OK; 1513 } 1514 1515 1516 // 1517 //#pragma mark - Partial Buffer Functions 1518 // 1519 1520 1521 static bool 1522 usb_disk_needs_partial_buffer(device_lun *lun, off_t position, size_t length, 1523 uint32 &blockPosition, uint16 &blockCount) 1524 { 1525 blockPosition = (uint32)(position / lun->block_size); 1526 if ((off_t)blockPosition * lun->block_size != position) 1527 return true; 1528 1529 blockCount = (uint16)(length / lun->block_size); 1530 if ((size_t)blockCount * lun->block_size != length) 1531 return true; 1532 1533 return false; 1534 } 1535 1536 1537 static status_t 1538 usb_disk_block_read(device_lun *lun, uint32 blockPosition, uint16 blockCount, 1539 void *buffer, size_t *length) 1540 { 1541 uint8 commandBlock[12]; 1542 memset(commandBlock, 0, sizeof(commandBlock)); 1543 if (lun->device->is_ufi) { 1544 commandBlock[0] = SCSI_READ_12; 1545 commandBlock[1] = lun->logical_unit_number << 5; 1546 commandBlock[2] = blockPosition >> 24; 1547 commandBlock[3] = blockPosition >> 16; 1548 commandBlock[4] = blockPosition >> 8; 1549 commandBlock[5] = blockPosition; 1550 commandBlock[6] = 0; // blockCount >> 24; 1551 commandBlock[7] = 0; // blockCount >> 16; 1552 commandBlock[8] = blockCount >> 8; 1553 commandBlock[9] = blockCount; 1554 1555 status_t result = B_OK; 1556 for (int tries = 0; tries < 5; tries++) { 1557 result = usb_disk_operation(lun, commandBlock, 12, buffer, length, 1558 true); 1559 if (result == B_OK) 1560 break; 1561 else 1562 snooze(10000); 1563 } 1564 return result; 1565 } else { 1566 commandBlock[0] = SCSI_READ_10; 1567 commandBlock[1] = 0; 1568 commandBlock[2] = blockPosition >> 24; 1569 commandBlock[3] = blockPosition >> 16; 1570 commandBlock[4] = blockPosition >> 8; 1571 commandBlock[5] = blockPosition; 1572 commandBlock[7] = blockCount >> 8; 1573 commandBlock[8] = blockCount; 1574 status_t result = usb_disk_operation(lun, commandBlock, 10, 1575 buffer, length, true); 1576 return result; 1577 } 1578 } 1579 1580 1581 static status_t 1582 usb_disk_block_write(device_lun *lun, uint32 blockPosition, uint16 blockCount, 1583 void *buffer, size_t *length) 1584 { 1585 uint8 commandBlock[12]; 1586 memset(commandBlock, 0, sizeof(commandBlock)); 1587 1588 if (lun->device->is_ufi) { 1589 commandBlock[0] = SCSI_WRITE_12; 1590 commandBlock[1] = lun->logical_unit_number << 5; 1591 commandBlock[2] = blockPosition >> 24; 1592 commandBlock[3] = blockPosition >> 16; 1593 commandBlock[4] = blockPosition >> 8; 1594 commandBlock[5] = blockPosition; 1595 commandBlock[6] = blockCount >> 24; 1596 commandBlock[7] = blockCount >> 16; 1597 commandBlock[8] = blockCount >> 8; 1598 commandBlock[9] = blockCount; 1599 1600 status_t result; 1601 result = usb_disk_operation(lun, commandBlock, 12, buffer, length, 1602 false); 1603 1604 int retry = 10; 1605 err_act action = err_act_ok; 1606 while (result == B_DEV_NO_MEDIA && retry > 0) { 1607 snooze(10000); 1608 result = usb_disk_request_sense(lun, &action); 1609 retry--; 1610 } 1611 1612 if (result == B_OK) 1613 lun->should_sync = true; 1614 return result; 1615 } else { 1616 commandBlock[0] = SCSI_WRITE_10; 1617 commandBlock[2] = blockPosition >> 24; 1618 commandBlock[3] = blockPosition >> 16; 1619 commandBlock[4] = blockPosition >> 8; 1620 commandBlock[5] = blockPosition; 1621 commandBlock[7] = blockCount >> 8; 1622 commandBlock[8] = blockCount; 1623 status_t result = usb_disk_operation(lun, commandBlock, 10, 1624 buffer, length, false); 1625 if (result == B_OK) 1626 lun->should_sync = true; 1627 return result; 1628 } 1629 } 1630 1631 1632 static status_t 1633 usb_disk_prepare_partial_buffer(device_lun *lun, off_t position, size_t length, 1634 void *&partialBuffer, void *&blockBuffer, uint32 &blockPosition, 1635 uint16 &blockCount) 1636 { 1637 blockPosition = (uint32)(position / lun->block_size); 1638 blockCount = (uint16)((uint32)((position + length + lun->block_size - 1) 1639 / lun->block_size) - blockPosition); 1640 size_t blockLength = blockCount * lun->block_size; 1641 blockBuffer = malloc(blockLength); 1642 if (blockBuffer == NULL) { 1643 TRACE_ALWAYS("no memory to allocate partial buffer\n"); 1644 return B_NO_MEMORY; 1645 } 1646 1647 status_t result = usb_disk_block_read(lun, blockPosition, blockCount, 1648 blockBuffer, &blockLength); 1649 if (result != B_OK) { 1650 TRACE_ALWAYS("block read failed when filling partial buffer: %s\n", 1651 strerror(result)); 1652 free(blockBuffer); 1653 return result; 1654 } 1655 1656 off_t offset = position - (off_t)blockPosition * lun->block_size; 1657 partialBuffer = (uint8 *)blockBuffer + offset; 1658 return B_OK; 1659 } 1660 1661 1662 // 1663 //#pragma mark - Driver Hooks 1664 // 1665 1666 1667 static status_t 1668 usb_disk_open(const char *name, uint32 flags, void **cookie) 1669 { 1670 TRACE("open(%s)\n", name); 1671 if (strncmp(name, DEVICE_NAME_BASE, strlen(DEVICE_NAME_BASE)) != 0) 1672 return B_NAME_NOT_FOUND; 1673 1674 int32 lastPart = 0; 1675 size_t nameLength = strlen(name); 1676 for (int32 i = nameLength - 1; i >= 0; i--) { 1677 if (name[i] == '/') { 1678 lastPart = i; 1679 break; 1680 } 1681 } 1682 1683 char rawName[nameLength + 4]; 1684 strncpy(rawName, name, lastPart + 1); 1685 rawName[lastPart + 1] = 0; 1686 strcat(rawName, "raw"); 1687 TRACE("opening raw device %s for %s\n", rawName, name); 1688 1689 mutex_lock(&gDeviceListLock); 1690 disk_device *device = gDeviceList; 1691 while (device) { 1692 for (uint8 i = 0; i < device->lun_count; i++) { 1693 device_lun *lun = device->luns[i]; 1694 if (strncmp(rawName, lun->name, 32) == 0) { 1695 // found the matching device/lun 1696 if (device->removed) { 1697 mutex_unlock(&gDeviceListLock); 1698 return B_ERROR; 1699 } 1700 1701 device->open_count++; 1702 *cookie = lun; 1703 mutex_unlock(&gDeviceListLock); 1704 return B_OK; 1705 } 1706 } 1707 1708 device = (disk_device *)device->link; 1709 } 1710 1711 mutex_unlock(&gDeviceListLock); 1712 return B_NAME_NOT_FOUND; 1713 } 1714 1715 1716 static status_t 1717 usb_disk_close(void *cookie) 1718 { 1719 TRACE("close()\n"); 1720 device_lun *lun = (device_lun *)cookie; 1721 disk_device *device = lun->device; 1722 1723 mutex_lock(&device->lock); 1724 if (!device->removed) 1725 usb_disk_synchronize(lun, false); 1726 mutex_unlock(&device->lock); 1727 1728 return B_OK; 1729 } 1730 1731 1732 static status_t 1733 usb_disk_free(void *cookie) 1734 { 1735 TRACE("free()\n"); 1736 mutex_lock(&gDeviceListLock); 1737 1738 device_lun *lun = (device_lun *)cookie; 1739 disk_device *device = lun->device; 1740 device->open_count--; 1741 if (device->open_count == 0 && device->removed) { 1742 // we can simply free the device here as it has been removed from 1743 // the device list in the device removed notification hook 1744 usb_disk_free_device_and_luns(device); 1745 } 1746 1747 mutex_unlock(&gDeviceListLock); 1748 return B_OK; 1749 } 1750 1751 1752 static inline void 1753 normalize_name(char *name, size_t nameLength) 1754 { 1755 bool wasSpace = false; 1756 size_t insertIndex = 0; 1757 for (size_t i = 0; i < nameLength; i++) { 1758 bool isSpace = name[i] == ' '; 1759 if (isSpace && wasSpace) 1760 continue; 1761 1762 name[insertIndex++] = name[i]; 1763 wasSpace = isSpace; 1764 } 1765 1766 if (insertIndex > 0 && name[insertIndex - 1] == ' ') 1767 insertIndex--; 1768 1769 name[insertIndex] = 0; 1770 } 1771 1772 1773 static status_t 1774 usb_disk_ioctl(void *cookie, uint32 op, void *buffer, size_t length) 1775 { 1776 device_lun *lun = (device_lun *)cookie; 1777 disk_device *device = lun->device; 1778 MutexLocker locker(&device->lock); 1779 if (device->removed) 1780 return B_DEV_NOT_READY; 1781 1782 switch (op) { 1783 case B_GET_DEVICE_SIZE: { 1784 if (lun->media_changed) { 1785 status_t result = usb_disk_update_capacity(lun); 1786 if (result != B_OK) 1787 return result; 1788 } 1789 1790 size_t size = lun->block_size * lun->block_count; 1791 return user_memcpy(buffer, &size, sizeof(size)); 1792 } 1793 1794 case B_GET_MEDIA_STATUS: 1795 { 1796 err_act action = err_act_ok; 1797 for (uint32 tries = 0; tries < 3; tries++) { 1798 status_t ready = usb_disk_test_unit_ready(lun, &action); 1799 if (ready == B_OK || ready == B_DEV_NO_MEDIA 1800 || (action != err_act_retry 1801 && action != err_act_many_retries)) { 1802 *(status_t *)buffer = ready; 1803 break; 1804 } 1805 snooze(500000); 1806 } 1807 TRACE("B_GET_MEDIA_STATUS: 0x%08" B_PRIx32 "\n", 1808 *(status_t *)buffer); 1809 return B_OK; 1810 } 1811 1812 case B_GET_GEOMETRY: 1813 { 1814 if (lun->media_changed) { 1815 status_t result = usb_disk_update_capacity(lun); 1816 if (result != B_OK) 1817 return result; 1818 } 1819 1820 device_geometry geometry; 1821 devfs_compute_geometry_size(&geometry, lun->block_count, 1822 lun->block_size); 1823 1824 geometry.device_type = lun->device_type; 1825 geometry.removable = lun->removable; 1826 geometry.read_only = lun->write_protected; 1827 geometry.write_once = lun->device_type == B_WORM; 1828 TRACE("B_GET_GEOMETRY: %" B_PRId32 " sectors at %" B_PRId32 1829 " bytes per sector\n", geometry.cylinder_count, 1830 geometry.bytes_per_sector); 1831 return user_memcpy(buffer, &geometry, sizeof(device_geometry)); 1832 } 1833 1834 case B_FLUSH_DRIVE_CACHE: 1835 TRACE("B_FLUSH_DRIVE_CACHE\n"); 1836 return usb_disk_synchronize(lun, true); 1837 1838 case B_EJECT_DEVICE: 1839 { 1840 uint8 commandBlock[12]; 1841 memset(commandBlock, 0, sizeof(commandBlock)); 1842 1843 commandBlock[0] = SCSI_START_STOP_UNIT_6; 1844 commandBlock[1] = lun->logical_unit_number << 5; 1845 commandBlock[4] = 2; 1846 1847 return usb_disk_operation(lun, commandBlock, 6, NULL, NULL, 1848 false); 1849 } 1850 1851 case B_LOAD_MEDIA: 1852 { 1853 uint8 commandBlock[12]; 1854 memset(commandBlock, 0, sizeof(commandBlock)); 1855 1856 commandBlock[0] = SCSI_START_STOP_UNIT_6; 1857 commandBlock[1] = lun->logical_unit_number << 5; 1858 commandBlock[4] = 3; 1859 1860 return usb_disk_operation(lun, commandBlock, 6, NULL, NULL, 1861 false); 1862 } 1863 1864 case B_GET_ICON: 1865 // We don't support this legacy ioctl anymore, but the two other 1866 // icon ioctls below instead. 1867 break; 1868 1869 case B_GET_ICON_NAME: 1870 { 1871 const char *iconName = "devices/drive-removable-media-usb"; 1872 char vendor[sizeof(lun->vendor_name)+1]; 1873 char product[sizeof(lun->product_name)+1]; 1874 1875 if (device->is_ufi) { 1876 iconName = "devices/drive-floppy-usb"; 1877 } 1878 1879 switch (lun->device_type) { 1880 case B_CD: 1881 case B_OPTICAL: 1882 iconName = "devices/drive-optical"; 1883 break; 1884 case B_TAPE: // TODO 1885 default: 1886 snprintf(vendor, sizeof(vendor), "%.8s", 1887 lun->vendor_name); 1888 snprintf(product, sizeof(product), "%.16s", 1889 lun->product_name); 1890 for (int i = 0; kIconMatches[i].icon; i++) { 1891 if (kIconMatches[i].vendor != NULL 1892 && strstr(vendor, kIconMatches[i].vendor) == NULL) 1893 continue; 1894 if (kIconMatches[i].product != NULL 1895 && strstr(product, kIconMatches[i].product) == NULL) 1896 continue; 1897 iconName = kIconMatches[i].name; 1898 } 1899 break; 1900 } 1901 return user_strlcpy((char *)buffer, iconName, 1902 B_FILE_NAME_LENGTH); 1903 } 1904 1905 case B_GET_VECTOR_ICON: 1906 { 1907 device_icon *icon = &kKeyIconData; 1908 char vendor[sizeof(lun->vendor_name)+1]; 1909 char product[sizeof(lun->product_name)+1]; 1910 1911 if (length != sizeof(device_icon)) 1912 return B_BAD_VALUE; 1913 1914 if (device->is_ufi) { 1915 // UFI is specific for floppy drives 1916 icon = &kFloppyIconData; 1917 } else { 1918 switch (lun->device_type) { 1919 case B_CD: 1920 case B_OPTICAL: 1921 icon = &kCDIconData; 1922 break; 1923 case B_TAPE: // TODO 1924 default: 1925 snprintf(vendor, sizeof(vendor), "%.8s", 1926 lun->vendor_name); 1927 snprintf(product, sizeof(product), "%.16s", 1928 lun->product_name); 1929 for (int i = 0; kIconMatches[i].icon; i++) { 1930 if (kIconMatches[i].vendor != NULL 1931 && strstr(vendor, 1932 kIconMatches[i].vendor) == NULL) 1933 continue; 1934 if (kIconMatches[i].product != NULL 1935 && strstr(product, 1936 kIconMatches[i].product) == NULL) 1937 continue; 1938 icon = kIconMatches[i].icon; 1939 } 1940 break; 1941 } 1942 } 1943 1944 device_icon iconData; 1945 if (user_memcpy(&iconData, buffer, sizeof(device_icon)) != B_OK) 1946 return B_BAD_ADDRESS; 1947 1948 if (iconData.icon_size >= icon->icon_size) { 1949 if (user_memcpy(iconData.icon_data, icon->icon_data, 1950 (size_t)icon->icon_size) != B_OK) 1951 return B_BAD_ADDRESS; 1952 } 1953 1954 iconData.icon_size = icon->icon_size; 1955 return user_memcpy(buffer, &iconData, sizeof(device_icon)); 1956 } 1957 1958 case B_GET_DEVICE_NAME: 1959 { 1960 size_t nameLength = sizeof(lun->vendor_name) 1961 + sizeof(lun->product_name) + sizeof(lun->product_revision) + 3; 1962 1963 char name[nameLength]; 1964 snprintf(name, nameLength, "%.8s %.16s %.4s", lun->vendor_name, 1965 lun->product_name, lun->product_revision); 1966 1967 normalize_name(name, nameLength); 1968 1969 status_t result = user_strlcpy((char *)buffer, name, length); 1970 if (result > 0) 1971 result = B_OK; 1972 1973 TRACE_ALWAYS("got device name \"%s\": %s\n", name, 1974 strerror(result)); 1975 return result; 1976 } 1977 } 1978 1979 TRACE_ALWAYS("unhandled ioctl %" B_PRId32 "\n", op); 1980 return B_DEV_INVALID_IOCTL; 1981 } 1982 1983 1984 static status_t 1985 usb_disk_read(void *cookie, off_t position, void *buffer, size_t *length) 1986 { 1987 if (buffer == NULL || length == NULL) 1988 return B_BAD_VALUE; 1989 1990 TRACE("read(%" B_PRIdOFF ", %ld)\n", position, *length); 1991 device_lun *lun = (device_lun *)cookie; 1992 disk_device *device = lun->device; 1993 mutex_lock(&device->lock); 1994 if (device->removed) { 1995 *length = 0; 1996 mutex_unlock(&device->lock); 1997 return B_DEV_NOT_READY; 1998 } 1999 2000 status_t result = B_ERROR; 2001 uint32 blockPosition = 0; 2002 uint16 blockCount = 0; 2003 bool needsPartial = usb_disk_needs_partial_buffer(lun, position, *length, 2004 blockPosition, blockCount); 2005 if (needsPartial) { 2006 void *partialBuffer = NULL; 2007 void *blockBuffer = NULL; 2008 result = usb_disk_prepare_partial_buffer(lun, position, *length, 2009 partialBuffer, blockBuffer, blockPosition, blockCount); 2010 if (result == B_OK) { 2011 if (IS_USER_ADDRESS(buffer)) 2012 result = user_memcpy(buffer, partialBuffer, *length); 2013 else 2014 memcpy(buffer, partialBuffer, *length); 2015 free(blockBuffer); 2016 } 2017 } else { 2018 result = usb_disk_block_read(lun, blockPosition, blockCount, buffer, 2019 length); 2020 } 2021 2022 mutex_unlock(&device->lock); 2023 if (result == B_OK) { 2024 TRACE("read successful with %ld bytes\n", *length); 2025 return B_OK; 2026 } 2027 2028 *length = 0; 2029 TRACE_ALWAYS("read failed: %s\n", strerror(result)); 2030 return result; 2031 } 2032 2033 2034 static status_t 2035 usb_disk_write(void *cookie, off_t position, const void *buffer, 2036 size_t *length) 2037 { 2038 if (buffer == NULL || length == NULL) 2039 return B_BAD_VALUE; 2040 2041 TRACE("write(%" B_PRIdOFF", %ld)\n", position, *length); 2042 device_lun *lun = (device_lun *)cookie; 2043 disk_device *device = lun->device; 2044 mutex_lock(&device->lock); 2045 if (device->removed) { 2046 *length = 0; 2047 mutex_unlock(&device->lock); 2048 return B_DEV_NOT_READY; 2049 } 2050 2051 status_t result = B_ERROR; 2052 uint32 blockPosition = 0; 2053 uint16 blockCount = 0; 2054 bool needsPartial = usb_disk_needs_partial_buffer(lun, position, 2055 *length, blockPosition, blockCount); 2056 if (needsPartial) { 2057 void *partialBuffer = NULL; 2058 void *blockBuffer = NULL; 2059 result = usb_disk_prepare_partial_buffer(lun, position, *length, 2060 partialBuffer, blockBuffer, blockPosition, blockCount); 2061 if (result == B_OK) { 2062 if (IS_USER_ADDRESS(buffer)) 2063 result = user_memcpy(partialBuffer, buffer, *length); 2064 else 2065 memcpy(partialBuffer, buffer, *length); 2066 } 2067 if (result == B_OK) { 2068 size_t blockLength = blockCount * lun->block_size; 2069 result = usb_disk_block_write(lun, blockPosition, blockCount, 2070 blockBuffer, &blockLength); 2071 free(blockBuffer); 2072 } 2073 } else { 2074 result = usb_disk_block_write(lun, blockPosition, blockCount, 2075 (void *)buffer, length); 2076 } 2077 2078 mutex_unlock(&device->lock); 2079 if (result == B_OK) { 2080 TRACE("write successful with %ld bytes\n", *length); 2081 return B_OK; 2082 } 2083 2084 *length = 0; 2085 TRACE_ALWAYS("write failed: %s\n", strerror(result)); 2086 return result; 2087 } 2088 2089 2090 // 2091 //#pragma mark - Driver Entry Points 2092 // 2093 2094 2095 status_t 2096 init_hardware() 2097 { 2098 TRACE("init_hardware()\n"); 2099 return B_OK; 2100 } 2101 2102 2103 status_t 2104 init_driver() 2105 { 2106 TRACE("init_driver()\n"); 2107 static usb_notify_hooks notifyHooks = { 2108 &usb_disk_device_added, 2109 &usb_disk_device_removed 2110 }; 2111 2112 static usb_support_descriptor supportedDevices[] = { 2113 { 0x08 /* mass storage */, 0x06 /* SCSI */, 0x50 /* bulk */, 0, 0 }, 2114 { 0x08 /* mass storage */, 0x02 /* ATAPI */, 0x50 /* bulk */, 0, 0 }, 2115 { 0x08 /* mass storage */, 0x05 /* ATAPI */, 0x50 /* bulk */, 0, 0 }, 2116 { 0x08 /* mass storage */, 0x04 /* UFI */, 0x00, 0, 0 } 2117 }; 2118 2119 gDeviceList = NULL; 2120 gDeviceCount = 0; 2121 gLunCount = 0; 2122 mutex_init(&gDeviceListLock, "usb_disk device list lock"); 2123 2124 TRACE("trying module %s\n", B_USB_MODULE_NAME); 2125 status_t result = get_module(B_USB_MODULE_NAME, 2126 (module_info **)&gUSBModule); 2127 if (result < B_OK) { 2128 TRACE_ALWAYS("getting module failed: %s\n", strerror(result)); 2129 mutex_destroy(&gDeviceListLock); 2130 return result; 2131 } 2132 2133 gUSBModule->register_driver(DRIVER_NAME, supportedDevices, 4, NULL); 2134 gUSBModule->install_notify(DRIVER_NAME, ¬ifyHooks); 2135 return B_OK; 2136 } 2137 2138 2139 void 2140 uninit_driver() 2141 { 2142 TRACE("uninit_driver()\n"); 2143 gUSBModule->uninstall_notify(DRIVER_NAME); 2144 mutex_lock(&gDeviceListLock); 2145 2146 if (gDeviceNames) { 2147 for (int32 i = 0; gDeviceNames[i]; i++) 2148 free(gDeviceNames[i]); 2149 free(gDeviceNames); 2150 gDeviceNames = NULL; 2151 } 2152 2153 mutex_destroy(&gDeviceListLock); 2154 put_module(B_USB_MODULE_NAME); 2155 } 2156 2157 2158 const char ** 2159 publish_devices() 2160 { 2161 TRACE("publish_devices()\n"); 2162 if (gDeviceNames) { 2163 for (int32 i = 0; gDeviceNames[i]; i++) 2164 free(gDeviceNames[i]); 2165 free(gDeviceNames); 2166 gDeviceNames = NULL; 2167 } 2168 2169 gDeviceNames = (char **)malloc(sizeof(char *) * (gLunCount + 1)); 2170 if (gDeviceNames == NULL) 2171 return NULL; 2172 2173 int32 index = 0; 2174 mutex_lock(&gDeviceListLock); 2175 disk_device *device = gDeviceList; 2176 while (device) { 2177 for (uint8 i = 0; i < device->lun_count; i++) 2178 gDeviceNames[index++] = strdup(device->luns[i]->name); 2179 2180 device = (disk_device *)device->link; 2181 } 2182 2183 gDeviceNames[index++] = NULL; 2184 mutex_unlock(&gDeviceListLock); 2185 return (const char **)gDeviceNames; 2186 } 2187 2188 2189 device_hooks * 2190 find_device(const char *name) 2191 { 2192 TRACE("find_device()\n"); 2193 static device_hooks hooks = { 2194 &usb_disk_open, 2195 &usb_disk_close, 2196 &usb_disk_free, 2197 &usb_disk_ioctl, 2198 &usb_disk_read, 2199 &usb_disk_write, 2200 NULL, 2201 NULL, 2202 NULL, 2203 NULL 2204 }; 2205 2206 return &hooks; 2207 } 2208