1 /* 2 * Copyright 2010, Haiku Inc. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Jérôme Duval, korli@users.berlios.de 7 */ 8 9 /* 10 Devices and messages reference: usb-modeswitch-data-20100826 11 */ 12 13 #include <ByteOrder.h> 14 #include <Drivers.h> 15 #include <KernelExport.h> 16 #include <lock.h> 17 #include <USB3.h> 18 19 #include <malloc.h> 20 #include <stdio.h> 21 #include <string.h> 22 23 #define DRIVER_NAME "usb_modeswitch" 24 25 #define TRACE_USB_MODESWITCH 1 26 #ifdef TRACE_USB_MODESWITCH 27 #define TRACE(x...) dprintf(DRIVER_NAME": "x) 28 #else 29 #define TRACE(x...) /* nothing */ 30 #endif 31 #define TRACE_ALWAYS(x...) dprintf(DRIVER_NAME": "x) 32 #define ENTER() TRACE("%s", __FUNCTION__) 33 34 35 enum msgType { 36 MSG_HUAWEI_1 = 0, 37 MSG_HUAWEI_2, 38 MSG_HUAWEI_3, 39 MSG_NOKIA_1, 40 MSG_OLIVETTI_1, 41 MSG_OLIVETTI_2, 42 MSG_OPTION_1, 43 MSG_ATHEROS_1, 44 MSG_ZTE_1, 45 MSG_ZTE_2, 46 MSG_ZTE_3, 47 MSG_NONE 48 }; 49 50 51 unsigned char kDevicesMsg[][31] = { 52 { /* MSG_HUAWEI_1 */ 53 0x55, 0x53, 0x42, 0x43, 0x12, 0x34, 0x56, 0x78, 54 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 55 0x06, 0x20, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 56 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 57 }, 58 { /* MSG_HUAWEI_2 */ 59 0x55, 0x53, 0x42, 0x43, 0x12, 0x34, 0x56, 0x78, 60 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x0a, 0x11, 61 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 62 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 63 }, 64 { /* MSG_HUAWEI_3 */ 65 0x55, 0x53, 0x42, 0x43, 0x12, 0x34, 0x56, 0x78, 66 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 67 0x06, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 68 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 69 }, 70 { /* MSG_NOKIA_1 */ 71 0x55, 0x53, 0x42, 0x43, 0x12, 0x34, 0x56, 0x78, 72 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x1b, 73 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 74 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 75 }, 76 { /* MSG_OLIVETTI_1 */ 77 0x55, 0x53, 0x42, 0x43, 0x12, 0x34, 0x56, 0x78, 78 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x1b, 79 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 80 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 81 }, 82 { /* MSG_OLIVETTI_2 */ 83 0x55, 0x53, 0x42, 0x43, 0x12, 0x34, 0x56, 0x78, 84 0xc0, 0x00, 0x00, 0x00, 0x80, 0x01, 0x06, 0x06, 85 0xf5, 0x04, 0x02, 0x52, 0x70, 0x00, 0x00, 0x00, 86 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 87 }, 88 { /* MSG_OPTION_1 */ 89 0x55, 0x53, 0x42, 0x43, 0x78, 0x56, 0x34, 0x12, 90 0x01, 0x00, 0x00, 0x00, 0x80, 0x00, 0x06, 0x10, 91 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 92 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 93 }, 94 { /* MSG_ATHEROS_1 */ 95 0x55, 0x53, 0x42, 0x43, 0x29, 0x00, 0x00, 0x00, 96 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x1b, 97 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 98 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 99 }, 100 { /* MSG_ZTE_1 */ 101 0x55, 0x53, 0x42, 0x43, 0x12, 0x34, 0x56, 0x78, 102 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x1e, 103 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 104 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 105 }, 106 { /* MSG_ZTE_2 */ 107 0x55, 0x53, 0x42, 0x43, 0x12, 0x34, 0x56, 0x79, 108 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x1b, 109 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 110 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 111 }, 112 { /* MSG_ZTE_3 */ 113 0x55, 0x53, 0x42, 0x43, 0x12, 0x34, 0x56, 0x70, 114 0x20, 0x00, 0x00, 0x00, 0x80, 0x00, 0x0c, 0x85, 115 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 116 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 117 } 118 }; 119 120 121 #define HUAWEI_VENDOR 0x12d1 122 #define NOKIA_VENDOR 0x0421 123 #define NOVATEL_VENDOR 0x1410 124 #define ZYDAS_VENDOR 0x0ace 125 #define ZTE_VENDOR 0x19d2 126 #define OLIVETTI_VENDOR 0x0b3c 127 #define OPTION_VENDOR 0x0af0 128 #define ATHEROS_VENDOR 0x0cf3 129 130 131 static const struct { 132 usb_support_descriptor desc; 133 msgType type, type2, type3; 134 } kDevices[] = { 135 {{ 0, 0, 0, HUAWEI_VENDOR, 0x101e}, MSG_HUAWEI_1}, 136 {{ 0, 0, 0, HUAWEI_VENDOR, 0x1446}, MSG_HUAWEI_1}, 137 {{ 0, 0, 0, HUAWEI_VENDOR, 0x1449}, MSG_HUAWEI_1}, 138 {{ 0, 0, 0, HUAWEI_VENDOR, 0x14ad}, MSG_HUAWEI_1}, 139 {{ 0, 0, 0, HUAWEI_VENDOR, 0x14b5}, MSG_HUAWEI_1}, 140 {{ 0, 0, 0, HUAWEI_VENDOR, 0x14b7}, MSG_HUAWEI_1}, 141 {{ 0, 0, 0, HUAWEI_VENDOR, 0x14ba}, MSG_HUAWEI_1}, 142 {{ 0, 0, 0, HUAWEI_VENDOR, 0x14c1}, MSG_HUAWEI_1}, 143 {{ 0, 0, 0, HUAWEI_VENDOR, 0x14c3}, MSG_HUAWEI_1}, 144 {{ 0, 0, 0, HUAWEI_VENDOR, 0x14c4}, MSG_HUAWEI_1}, 145 {{ 0, 0, 0, HUAWEI_VENDOR, 0x14c5}, MSG_HUAWEI_1}, 146 {{ 0, 0, 0, HUAWEI_VENDOR, 0x14d1}, MSG_HUAWEI_1}, 147 {{ 0, 0, 0, HUAWEI_VENDOR, 0x14fe}, MSG_HUAWEI_1}, 148 {{ 0, 0, 0, HUAWEI_VENDOR, 0x1505}, MSG_HUAWEI_1}, 149 {{ 0, 0, 0, HUAWEI_VENDOR, 0x151a}, MSG_HUAWEI_1}, 150 {{ 0, 0, 0, HUAWEI_VENDOR, 0x1520}, MSG_HUAWEI_1}, 151 {{ 0, 0, 0, HUAWEI_VENDOR, 0x1521}, MSG_HUAWEI_1}, 152 {{ 0, 0, 0, HUAWEI_VENDOR, 0x1523}, MSG_HUAWEI_1}, 153 {{ 0, 0, 0, HUAWEI_VENDOR, 0x1526}, MSG_HUAWEI_1}, 154 {{ 0, 0, 0, HUAWEI_VENDOR, 0x1553}, MSG_HUAWEI_1}, 155 {{ 0, 0, 0, HUAWEI_VENDOR, 0x1557}, MSG_HUAWEI_1}, 156 {{ 0, 0, 0, HUAWEI_VENDOR, 0x155b}, MSG_HUAWEI_1}, 157 {{ 0, 0, 0, HUAWEI_VENDOR, 0x1c0b}, MSG_HUAWEI_1}, 158 {{ 0, 0, 0, HUAWEI_VENDOR, 0x1c24}, MSG_HUAWEI_1}, 159 {{ 0, 0, 0, HUAWEI_VENDOR, 0x1f11}, MSG_HUAWEI_1}, 160 {{ 0, 0, 0, HUAWEI_VENDOR, 0x1030}, MSG_HUAWEI_2}, 161 {{ 0, 0, 0, HUAWEI_VENDOR, 0x1031}, MSG_HUAWEI_2}, 162 {{ 0, 0, 0, HUAWEI_VENDOR, 0x1f01}, MSG_HUAWEI_3}, 163 {{ 0, 0, 0, NOKIA_VENDOR, 0x060c}, MSG_NOKIA_1}, 164 {{ 0, 0, 0, NOKIA_VENDOR, 0x0610}, MSG_NOKIA_1}, 165 {{ 0, 0, 0, NOKIA_VENDOR, 0x061d}, MSG_NOKIA_1}, 166 {{ 0, 0, 0, NOKIA_VENDOR, 0x0622}, MSG_NOKIA_1}, 167 {{ 0, 0, 0, NOKIA_VENDOR, 0x0627}, MSG_NOKIA_1}, 168 {{ 0, 0, 0, NOKIA_VENDOR, 0x062c}, MSG_NOKIA_1}, 169 {{ 0, 0, 0, NOKIA_VENDOR, 0x0632}, MSG_NOKIA_1}, 170 {{ 0, 0, 0, NOKIA_VENDOR, 0x0637}, MSG_NOKIA_1}, 171 {{ 0, 0, 0, NOVATEL_VENDOR, 0x5010}, MSG_NOKIA_1}, 172 {{ 0, 0, 0, NOVATEL_VENDOR, 0x5020}, MSG_NOKIA_1}, 173 {{ 0, 0, 0, NOVATEL_VENDOR, 0x5030}, MSG_NOKIA_1}, 174 {{ 0, 0, 0, NOVATEL_VENDOR, 0x5031}, MSG_NOKIA_1}, 175 {{ 0, 0, 0, NOVATEL_VENDOR, 0x5041}, MSG_NOKIA_1}, 176 {{ 0, 0, 0, NOVATEL_VENDOR, 0x5059}, MSG_NOKIA_1}, 177 {{ 0, 0, 0, NOVATEL_VENDOR, 0x7001}, MSG_NOKIA_1}, 178 {{ 0, 0, 0, ZYDAS_VENDOR, 0x2011}, MSG_NOKIA_1}, 179 {{ 0, 0, 0, ZYDAS_VENDOR, 0x20ff}, MSG_NOKIA_1}, 180 {{ 0, 0, 0, ZTE_VENDOR, 0x0013}, MSG_NOKIA_1}, 181 {{ 0, 0, 0, ZTE_VENDOR, 0x0026}, MSG_NOKIA_1}, 182 {{ 0, 0, 0, ZTE_VENDOR, 0x0031}, MSG_NOKIA_1}, 183 {{ 0, 0, 0, ZTE_VENDOR, 0x0083}, MSG_NOKIA_1}, 184 {{ 0, 0, 0, ZTE_VENDOR, 0x0101}, MSG_NOKIA_1}, 185 {{ 0, 0, 0, ZTE_VENDOR, 0x0115}, MSG_NOKIA_1}, 186 {{ 0, 0, 0, ZTE_VENDOR, 0x0120}, MSG_NOKIA_1}, 187 {{ 0, 0, 0, ZTE_VENDOR, 0x0169}, MSG_NOKIA_1}, 188 {{ 0, 0, 0, ZTE_VENDOR, 0x0325}, MSG_NOKIA_1}, 189 {{ 0, 0, 0, ZTE_VENDOR, 0x1001}, MSG_NOKIA_1}, 190 {{ 0, 0, 0, ZTE_VENDOR, 0x1007}, MSG_NOKIA_1}, 191 {{ 0, 0, 0, ZTE_VENDOR, 0x1009}, MSG_NOKIA_1}, 192 {{ 0, 0, 0, ZTE_VENDOR, 0x1013}, MSG_NOKIA_1}, 193 {{ 0, 0, 0, ZTE_VENDOR, 0x1017}, MSG_NOKIA_1}, 194 {{ 0, 0, 0, ZTE_VENDOR, 0x1171}, MSG_NOKIA_1}, 195 {{ 0, 0, 0, ZTE_VENDOR, 0x1175}, MSG_NOKIA_1}, 196 {{ 0, 0, 0, ZTE_VENDOR, 0x1179}, MSG_NOKIA_1}, 197 {{ 0, 0, 0, ZTE_VENDOR, 0x1201}, MSG_NOKIA_1}, 198 {{ 0, 0, 0, ZTE_VENDOR, 0x1523}, MSG_NOKIA_1}, 199 {{ 0, 0, 0, ZTE_VENDOR, 0xffde}, MSG_NOKIA_1}, 200 {{ 0, 0, 0, ZTE_VENDOR, 0x0003}, MSG_ZTE_1, MSG_ZTE_2}, 201 {{ 0, 0, 0, ZTE_VENDOR, 0x0053}, MSG_ZTE_1, MSG_ZTE_2}, 202 {{ 0, 0, 0, ZTE_VENDOR, 0x0103}, MSG_ZTE_1, MSG_ZTE_2}, 203 {{ 0, 0, 0, ZTE_VENDOR, 0x0154}, MSG_ZTE_1, MSG_ZTE_2}, 204 {{ 0, 0, 0, ZTE_VENDOR, 0x1224}, MSG_ZTE_1, MSG_ZTE_2}, 205 {{ 0, 0, 0, ZTE_VENDOR, 0x1517}, MSG_ZTE_1, MSG_ZTE_2}, 206 {{ 0, 0, 0, ZTE_VENDOR, 0x1542}, MSG_ZTE_1, MSG_ZTE_2}, 207 {{ 0, 0, 0, ZTE_VENDOR, 0x0149}, MSG_ZTE_1, MSG_ZTE_2, MSG_ZTE_3}, 208 {{ 0, 0, 0, ZTE_VENDOR, 0x2000}, MSG_ZTE_1, MSG_ZTE_2, MSG_ZTE_3}, 209 {{ 0, 0, 0, OLIVETTI_VENDOR, 0xc700}, MSG_OLIVETTI_1}, 210 {{ 0, 0, 0, OLIVETTI_VENDOR, 0xf000}, MSG_OLIVETTI_2}, 211 {{ 0, 0, 0, OPTION_VENDOR, 0x6711}, MSG_OPTION_1}, 212 {{ 0, 0, 0, OPTION_VENDOR, 0x6731}, MSG_OPTION_1}, 213 {{ 0, 0, 0, OPTION_VENDOR, 0x6751}, MSG_OPTION_1}, 214 {{ 0, 0, 0, OPTION_VENDOR, 0x6771}, MSG_OPTION_1}, 215 {{ 0, 0, 0, OPTION_VENDOR, 0x6791}, MSG_OPTION_1}, 216 {{ 0, 0, 0, OPTION_VENDOR, 0x6811}, MSG_OPTION_1}, 217 {{ 0, 0, 0, OPTION_VENDOR, 0x6911}, MSG_OPTION_1}, 218 {{ 0, 0, 0, OPTION_VENDOR, 0x6951}, MSG_OPTION_1}, 219 {{ 0, 0, 0, OPTION_VENDOR, 0x6971}, MSG_OPTION_1}, 220 {{ 0, 0, 0, OPTION_VENDOR, 0x7011}, MSG_OPTION_1}, 221 {{ 0, 0, 0, OPTION_VENDOR, 0x7031}, MSG_OPTION_1}, 222 {{ 0, 0, 0, OPTION_VENDOR, 0x7051}, MSG_OPTION_1}, 223 {{ 0, 0, 0, OPTION_VENDOR, 0x7071}, MSG_OPTION_1}, 224 {{ 0, 0, 0, OPTION_VENDOR, 0x7111}, MSG_OPTION_1}, 225 {{ 0, 0, 0, OPTION_VENDOR, 0x7211}, MSG_OPTION_1}, 226 {{ 0, 0, 0, OPTION_VENDOR, 0x7251}, MSG_OPTION_1}, 227 {{ 0, 0, 0, OPTION_VENDOR, 0x7271}, MSG_OPTION_1}, 228 {{ 0, 0, 0, OPTION_VENDOR, 0x7301}, MSG_OPTION_1}, 229 {{ 0, 0, 0, OPTION_VENDOR, 0x7311}, MSG_OPTION_1}, 230 {{ 0, 0, 0, OPTION_VENDOR, 0x7361}, MSG_OPTION_1}, 231 {{ 0, 0, 0, OPTION_VENDOR, 0x7381}, MSG_OPTION_1}, 232 {{ 0, 0, 0, OPTION_VENDOR, 0x7401}, MSG_OPTION_1}, 233 {{ 0, 0, 0, OPTION_VENDOR, 0x7501}, MSG_OPTION_1}, 234 {{ 0, 0, 0, OPTION_VENDOR, 0x7601}, MSG_OPTION_1}, 235 {{ 0, 0, 0, OPTION_VENDOR, 0x7701}, MSG_OPTION_1}, 236 {{ 0, 0, 0, OPTION_VENDOR, 0x7706}, MSG_OPTION_1}, 237 {{ 0, 0, 0, OPTION_VENDOR, 0x7801}, MSG_OPTION_1}, 238 {{ 0, 0, 0, OPTION_VENDOR, 0x7901}, MSG_OPTION_1}, 239 {{ 0, 0, 0, OPTION_VENDOR, 0x8006}, MSG_OPTION_1}, 240 {{ 0, 0, 0, OPTION_VENDOR, 0x8200}, MSG_OPTION_1}, 241 {{ 0, 0, 0, OPTION_VENDOR, 0x8201}, MSG_OPTION_1}, 242 {{ 0, 0, 0, OPTION_VENDOR, 0x8300}, MSG_OPTION_1}, 243 {{ 0, 0, 0, OPTION_VENDOR, 0x8302}, MSG_OPTION_1}, 244 {{ 0, 0, 0, OPTION_VENDOR, 0x8304}, MSG_OPTION_1}, 245 {{ 0, 0, 0, OPTION_VENDOR, 0x8400}, MSG_OPTION_1}, 246 {{ 0, 0, 0, OPTION_VENDOR, 0x8600}, MSG_OPTION_1}, 247 {{ 0, 0, 0, OPTION_VENDOR, 0x8800}, MSG_OPTION_1}, 248 {{ 0, 0, 0, OPTION_VENDOR, 0x8900}, MSG_OPTION_1}, 249 {{ 0, 0, 0, OPTION_VENDOR, 0x9000}, MSG_OPTION_1}, 250 {{ 0, 0, 0, OPTION_VENDOR, 0xc031}, MSG_OPTION_1}, 251 {{ 0, 0, 0, OPTION_VENDOR, 0xc100}, MSG_OPTION_1}, 252 {{ 0, 0, 0, OPTION_VENDOR, 0xc031}, MSG_OPTION_1}, 253 {{ 0, 0, 0, OPTION_VENDOR, 0xd013}, MSG_OPTION_1}, 254 {{ 0, 0, 0, OPTION_VENDOR, 0xd031}, MSG_OPTION_1}, 255 {{ 0, 0, 0, OPTION_VENDOR, 0xd033}, MSG_OPTION_1}, 256 {{ 0, 0, 0, OPTION_VENDOR, 0xd035}, MSG_OPTION_1}, 257 {{ 0, 0, 0, OPTION_VENDOR, 0xd055}, MSG_OPTION_1}, 258 {{ 0, 0, 0, OPTION_VENDOR, 0xd057}, MSG_OPTION_1}, 259 {{ 0, 0, 0, OPTION_VENDOR, 0xd058}, MSG_OPTION_1}, 260 {{ 0, 0, 0, OPTION_VENDOR, 0xd155}, MSG_OPTION_1}, 261 {{ 0, 0, 0, OPTION_VENDOR, 0xd157}, MSG_OPTION_1}, 262 {{ 0, 0, 0, OPTION_VENDOR, 0xd255}, MSG_OPTION_1}, 263 {{ 0, 0, 0, OPTION_VENDOR, 0xd257}, MSG_OPTION_1}, 264 {{ 0, 0, 0, OPTION_VENDOR, 0xd357}, MSG_OPTION_1}, 265 {{ 0, 0, 0, ATHEROS_VENDOR, 0x20ff}, MSG_ATHEROS_1}, 266 }; 267 static uint32 kDevicesCount = sizeof(kDevices) / sizeof(kDevices[0]); 268 269 270 typedef struct _my_device { 271 usb_device device; 272 bool removed; 273 mutex lock; 274 struct _my_device *link; 275 276 // device state 277 usb_pipe bulk_in; 278 usb_pipe bulk_out; 279 uint8 interface; 280 uint8 alternate_setting; 281 282 // used to store callback information 283 sem_id notify; 284 status_t status; 285 size_t actual_length; 286 287 msgType type[3]; 288 } my_device; 289 290 291 int32 api_version = B_CUR_DRIVER_API_VERSION; 292 static usb_module_info *gUSBModule = NULL; 293 static my_device *gDeviceList = NULL; 294 static uint32 gDeviceCount = 0; 295 static mutex gDeviceListLock; 296 297 298 // 299 //#pragma mark - Device Allocation Helper Functions 300 // 301 302 303 static void 304 my_free_device(my_device *device) 305 { 306 mutex_lock(&device->lock); 307 mutex_destroy(&device->lock); 308 delete_sem(device->notify); 309 free(device); 310 } 311 312 313 // 314 //#pragma mark - Bulk-only Functions 315 // 316 317 318 static void 319 my_callback(void *cookie, status_t status, void *data, 320 size_t actualLength) 321 { 322 my_device *device = (my_device *)cookie; 323 device->status = status; 324 device->actual_length = actualLength; 325 release_sem(device->notify); 326 } 327 328 329 static status_t 330 my_transfer_data(my_device *device, bool directionIn, void *data, 331 size_t dataLength) 332 { 333 status_t result = gUSBModule->queue_bulk(directionIn ? device->bulk_in 334 : device->bulk_out, data, dataLength, my_callback, device); 335 if (result != B_OK) { 336 TRACE_ALWAYS("failed to queue data transfer\n"); 337 return result; 338 } 339 340 do { 341 bigtime_t timeout = directionIn ? 500000 : 500000; 342 result = acquire_sem_etc(device->notify, 1, B_RELATIVE_TIMEOUT, 343 timeout); 344 if (result == B_TIMED_OUT) { 345 // Cancel the transfer and collect the sem that should now be 346 // released through the callback on cancel. Handling of device 347 // reset is done in usb_printer_operation() when it detects that 348 // the transfer failed. 349 gUSBModule->cancel_queued_transfers(directionIn ? device->bulk_in 350 : device->bulk_out); 351 acquire_sem_etc(device->notify, 1, B_RELATIVE_TIMEOUT, 0); 352 } 353 } while (result == B_INTERRUPTED); 354 355 if (result != B_OK) { 356 TRACE_ALWAYS("acquire_sem failed while waiting for data transfer\n"); 357 return result; 358 } 359 360 return B_OK; 361 } 362 363 364 enum msgType 365 my_get_msg_type(const usb_device_descriptor *desc, int index) 366 { 367 for (uint32 i = 0; i < kDevicesCount; i++) { 368 if (kDevices[i].desc.dev_class != 0x0 369 && kDevices[i].desc.dev_class != desc->device_class) 370 continue; 371 if (kDevices[i].desc.dev_subclass != 0x0 372 && kDevices[i].desc.dev_subclass != desc->device_subclass) 373 continue; 374 if (kDevices[i].desc.dev_protocol != 0x0 375 && kDevices[i].desc.dev_protocol != desc->device_protocol) 376 continue; 377 if (kDevices[i].desc.vendor != 0x0 378 && kDevices[i].desc.vendor != desc->vendor_id) 379 continue; 380 if (kDevices[i].desc.product != 0x0 381 && kDevices[i].desc.product != desc->product_id) 382 continue; 383 switch (index) { 384 case 0: 385 return kDevices[i].type; 386 case 1: 387 return kDevices[i].type2; 388 case 2: 389 return kDevices[i].type3; 390 } 391 392 } 393 394 return MSG_NONE; 395 } 396 397 398 399 status_t 400 my_modeswitch(my_device* device) 401 { 402 status_t err = B_OK; 403 if (device->type[0] == MSG_NONE) 404 return B_OK; 405 for (int i = 0; i < 3; i++) { 406 if (device->type[i] == MSG_NONE) 407 break; 408 409 err = my_transfer_data(device, false, kDevicesMsg[device->type[i]], 410 sizeof(kDevicesMsg[device->type[i]])); 411 if (err != B_OK) { 412 TRACE_ALWAYS("send message %d failed\n", i + 1); 413 return err; 414 } 415 416 TRACE("device switched: %p\n", device); 417 418 char data[36]; 419 err = my_transfer_data(device, true, data, sizeof(data)); 420 if (err != B_OK) { 421 TRACE_ALWAYS("receive response %d failed 0x%lx\n", 422 i + 1, device->status); 423 return err; 424 } 425 TRACE("device switched (response length %ld)\n", device->actual_length); 426 } 427 428 TRACE("device switched: %p\n", device); 429 430 return B_OK; 431 } 432 433 434 // 435 //#pragma mark - Device Attach/Detach Notifications and Callback 436 // 437 438 439 static status_t 440 my_device_added(usb_device newDevice, void **cookie) 441 { 442 TRACE("device_added(0x%08lx)\n", newDevice); 443 my_device *device = (my_device *)malloc(sizeof(my_device)); 444 device->device = newDevice; 445 device->removed = false; 446 device->interface = 0xff; 447 device->alternate_setting = 0; 448 449 // scan through the interfaces to find our bulk-only data interface 450 const usb_configuration_info *configuration = 451 gUSBModule->get_configuration(newDevice); 452 if (configuration == NULL) { 453 free(device); 454 return B_ERROR; 455 } 456 457 for (size_t i = 0; i < configuration->interface_count; i++) { 458 usb_interface_info *interface = configuration->interface[i].active; 459 if (interface == NULL) 460 continue; 461 462 if (true) { 463 464 bool hasIn = false; 465 bool hasOut = false; 466 for (size_t j = 0; j < interface->endpoint_count; j++) { 467 usb_endpoint_info *endpoint = &interface->endpoint[j]; 468 if (endpoint == NULL 469 || endpoint->descr->attributes != USB_ENDPOINT_ATTR_BULK) 470 continue; 471 472 if (!hasIn && (endpoint->descr->endpoint_address 473 & USB_ENDPOINT_ADDR_DIR_IN)) { 474 device->bulk_in = endpoint->handle; 475 hasIn = true; 476 } else if (!hasOut && (endpoint->descr->endpoint_address 477 & USB_ENDPOINT_ADDR_DIR_IN) == 0) { 478 device->bulk_out = endpoint->handle; 479 hasOut = true; 480 } 481 482 if (hasIn && hasOut) 483 break; 484 } 485 486 if (!(hasIn && hasOut)) 487 continue; 488 489 device->interface = interface->descr->interface_number; 490 device->alternate_setting = interface->descr->alternate_setting; 491 492 break; 493 } 494 } 495 496 if (device->interface == 0xff) { 497 TRACE_ALWAYS("no valid interface found\n"); 498 free(device); 499 return B_ERROR; 500 } 501 502 const usb_device_descriptor *descriptor 503 = gUSBModule->get_device_descriptor(newDevice); 504 if (descriptor == NULL) { 505 free(device); 506 return B_ERROR; 507 } 508 for (int i = 0; i < 3; i++) { 509 device->type[i] = my_get_msg_type(descriptor, i); 510 } 511 512 mutex_init(&device->lock, DRIVER_NAME " device lock"); 513 514 device->notify = create_sem(0, DRIVER_NAME " callback notify"); 515 if (device->notify < B_OK) { 516 mutex_destroy(&device->lock); 517 free(device); 518 return device->notify; 519 } 520 521 mutex_lock(&gDeviceListLock); 522 device->link = gDeviceList; 523 gDeviceList = device; 524 mutex_unlock(&gDeviceListLock); 525 526 *cookie = device; 527 528 return my_modeswitch(device); 529 } 530 531 532 static status_t 533 my_device_removed(void *cookie) 534 { 535 TRACE("device_removed(0x%08lx)\n", (uint32)cookie); 536 my_device *device = (my_device *)cookie; 537 538 mutex_lock(&gDeviceListLock); 539 if (gDeviceList == device) { 540 gDeviceList = device->link; 541 } else { 542 my_device *element = gDeviceList; 543 while (element) { 544 if (element->link == device) { 545 element->link = device->link; 546 break; 547 } 548 549 element = element->link; 550 } 551 } 552 gDeviceCount--; 553 554 device->removed = true; 555 gUSBModule->cancel_queued_transfers(device->bulk_in); 556 gUSBModule->cancel_queued_transfers(device->bulk_out); 557 my_free_device(device); 558 559 mutex_unlock(&gDeviceListLock); 560 return B_OK; 561 } 562 563 564 // 565 //#pragma mark - Driver Entry Points 566 // 567 568 569 status_t 570 init_hardware() 571 { 572 TRACE("init_hardware()\n"); 573 return B_OK; 574 } 575 576 577 status_t 578 init_driver() 579 { 580 TRACE("init_driver()\n"); 581 static usb_notify_hooks notifyHooks = { 582 &my_device_added, 583 &my_device_removed 584 }; 585 586 gDeviceList = NULL; 587 gDeviceCount = 0; 588 mutex_init(&gDeviceListLock, DRIVER_NAME " device list lock"); 589 590 TRACE("trying module %s\n", B_USB_MODULE_NAME); 591 status_t result = get_module(B_USB_MODULE_NAME, 592 (module_info **)&gUSBModule); 593 if (result < B_OK) { 594 TRACE_ALWAYS("getting module failed 0x%08lx\n", result); 595 mutex_destroy(&gDeviceListLock); 596 return result; 597 } 598 599 size_t descriptorsSize = kDevicesCount * sizeof(usb_support_descriptor); 600 usb_support_descriptor *supportedDevices = 601 (usb_support_descriptor *)malloc(descriptorsSize); 602 if (supportedDevices == NULL) { 603 TRACE_ALWAYS("descriptor allocation failed\n"); 604 put_module(B_USB_MODULE_NAME); 605 mutex_destroy(&gDeviceListLock); 606 return result; 607 } 608 609 for (uint32 i = 0; i < kDevicesCount; i++) 610 supportedDevices[i] = kDevices[i].desc; 611 612 gUSBModule->register_driver(DRIVER_NAME, supportedDevices, kDevicesCount, 613 NULL); 614 gUSBModule->install_notify(DRIVER_NAME, ¬ifyHooks); 615 free(supportedDevices); 616 return B_OK; 617 } 618 619 620 void 621 uninit_driver() 622 { 623 TRACE("uninit_driver()\n"); 624 gUSBModule->uninstall_notify(DRIVER_NAME); 625 mutex_lock(&gDeviceListLock); 626 mutex_destroy(&gDeviceListLock); 627 put_module(B_USB_MODULE_NAME); 628 } 629 630 631 const char ** 632 publish_devices() 633 { 634 TRACE("publish_devices()\n"); 635 return NULL; 636 } 637 638 639 device_hooks * 640 find_device(const char *name) 641 { 642 TRACE("find_device()\n"); 643 return NULL; 644 } 645