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 = 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 sem_id callbackSem = create_sem(0, DRIVER_NAME " callback notify"); 535 if (callbackSem < B_OK) { 536 mutex_destroy(&device->lock); 537 free(device); 538 return callbackSem; 539 } 540 device->notify = callbackSem; 541 542 mutex_lock(&gDeviceListLock); 543 device->link = gDeviceList; 544 gDeviceList = device; 545 mutex_unlock(&gDeviceListLock); 546 547 *cookie = device; 548 549 return my_modeswitch(device); 550 } 551 552 553 static status_t 554 my_device_removed(void *cookie) 555 { 556 TRACE("device_removed(%p)\n", cookie); 557 my_device *device = (my_device *)cookie; 558 559 mutex_lock(&gDeviceListLock); 560 if (gDeviceList == device) { 561 gDeviceList = device->link; 562 } else { 563 my_device *element = gDeviceList; 564 while (element) { 565 if (element->link == device) { 566 element->link = device->link; 567 break; 568 } 569 570 element = element->link; 571 } 572 } 573 gDeviceCount--; 574 575 device->removed = true; 576 gUSBModule->cancel_queued_transfers(device->bulk_in); 577 gUSBModule->cancel_queued_transfers(device->bulk_out); 578 my_free_device(device); 579 580 mutex_unlock(&gDeviceListLock); 581 return B_OK; 582 } 583 584 585 // 586 //#pragma mark - Driver Entry Points 587 // 588 589 590 status_t 591 init_hardware() 592 { 593 TRACE("init_hardware()\n"); 594 return B_OK; 595 } 596 597 598 status_t 599 init_driver() 600 { 601 TRACE("init_driver()\n"); 602 static usb_notify_hooks notifyHooks = { 603 &my_device_added, 604 &my_device_removed 605 }; 606 607 gDeviceList = NULL; 608 gDeviceCount = 0; 609 mutex_init(&gDeviceListLock, DRIVER_NAME " device list lock"); 610 611 TRACE("trying module %s\n", B_USB_MODULE_NAME); 612 status_t result = get_module(B_USB_MODULE_NAME, 613 (module_info **)&gUSBModule); 614 if (result < B_OK) { 615 TRACE_ALWAYS("getting module failed 0x%08" B_PRIx32 "\n", result); 616 mutex_destroy(&gDeviceListLock); 617 return result; 618 } 619 620 size_t descriptorsSize = kDevicesCount * sizeof(usb_support_descriptor); 621 usb_support_descriptor *supportedDevices = 622 (usb_support_descriptor *)malloc(descriptorsSize); 623 if (supportedDevices == NULL) { 624 TRACE_ALWAYS("descriptor allocation failed\n"); 625 put_module(B_USB_MODULE_NAME); 626 mutex_destroy(&gDeviceListLock); 627 return result; 628 } 629 630 for (uint32 i = 0; i < kDevicesCount; i++) 631 supportedDevices[i] = kDevices[i].desc; 632 633 gUSBModule->register_driver(DRIVER_NAME, supportedDevices, kDevicesCount, 634 NULL); 635 gUSBModule->install_notify(DRIVER_NAME, ¬ifyHooks); 636 free(supportedDevices); 637 return B_OK; 638 } 639 640 641 void 642 uninit_driver() 643 { 644 TRACE("uninit_driver()\n"); 645 gUSBModule->uninstall_notify(DRIVER_NAME); 646 mutex_lock(&gDeviceListLock); 647 mutex_destroy(&gDeviceListLock); 648 put_module(B_USB_MODULE_NAME); 649 } 650 651 652 const char ** 653 publish_devices() 654 { 655 TRACE("publish_devices()\n"); 656 return NULL; 657 } 658 659 660 device_hooks * 661 find_device(const char *name) 662 { 663 TRACE("find_device()\n"); 664 return NULL; 665 } 666