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