- Create another branch for networking fixes
[reactos.git] / drivers / usb / nt4compat / usbdriver / umss.c
1 /**
2 * umss.c - USB driver stack project for Windows NT 4.0
3 *
4 * Copyright (c) 2002-2004 Zhiming mypublic99@yahoo.com
5 *
6 * This program/include file is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as published
8 * by the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program/include file is distributed in the hope that it will be
12 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
13 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * this program (in the main directory of the distribution, the file
18 * COPYING); if not, write to the Free Software Foundation,Inc., 59 Temple
19 * Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22 #include "usbdriver.h"
23
24 #include <srb.h>
25 #include <ntddscsi.h>
26 #include <scsi.h>
27
28 #define UMSS_EXIT_DISPATCH( dev_OBJ, staTUS, iRp ) \
29 {\
30 iRp->IoStatus.Status = staTUS;\
31 if( staTUS != STATUS_PENDING)\
32 {\
33 IoCompleteRequest( iRp, IO_NO_INCREMENT);\
34 return staTUS;\
35 }\
36 IoMarkIrpPending( iRp );\
37 IoStartPacket( dev_OBJ, iRp, NULL, NULL ); \
38 return STATUS_PENDING;\
39 }
40
41 #define UMSS_COMPLETE_START_IO( dev_OBJ, staTUS, iRP ) \
42 {\
43 iRP->IoStatus.Status = staTUS;\
44 if( staTUS != STATUS_PENDING )\
45 {\
46 IoStartNextPacket( dev_OBJ, FALSE );\
47 IoCompleteRequest( iRP, IO_NO_INCREMENT );\
48 }\
49 return;\
50 }
51
52 extern VOID gendrv_startio(IN PDEVICE_OBJECT dev_obj, IN PIRP irp);
53
54 NTSYSAPI NTSTATUS NTAPI ZwLoadDriver(IN PUNICODE_STRING DriverServiceName);
55
56 NTSYSAPI
57 NTSTATUS
58 NTAPI
59 ObOpenObjectByName(IN POBJECT_ATTRIBUTES ObjectAttributes,
60 IN POBJECT_TYPE ObjectType OPTIONAL,
61 IN KPROCESSOR_MODE AccessMode,
62 IN OUT PACCESS_STATE AccessState OPTIONAL,
63 IN ACCESS_MASK DesiredAccess OPTIONAL,
64 IN OUT PVOID ParseContext OPTIONAL, OUT PHANDLE Handle);
65
66 VOID NTAPI umss_start_io(IN PDEVICE_OBJECT dev_obj, IN PIRP irp);
67 NTSTATUS umss_port_dispatch_routine(PDEVICE_OBJECT pdev_obj, PIRP irp);
68 BOOLEAN umss_connect(PDEV_CONNECT_DATA dev_mgr, DEV_HANDLE dev_handle);
69 BOOLEAN umss_disconnect(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle);
70 BOOLEAN umss_stop(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle);
71 NTSTATUS umss_dispatch_routine(PDEVICE_OBJECT pdev_obj, PIRP irp);
72 VOID umss_set_cfg_completion(PURB purb, PVOID pcontext);
73 VOID NTAPI umss_start_create_device(IN PVOID Parameter);
74 BOOLEAN umss_delete_device(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdrvr, PDEVICE_OBJECT dev_obj, BOOLEAN is_if);
75 BOOLEAN umss_stop(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle);
76 NTSTATUS umss_process_srb(PDEVICE_OBJECT dev_obj, PIRP irp);
77 VOID umss_load_class_driver(PVOID context);
78 BOOLEAN umss_tsc_to_sff(PIO_PACKET io_packet);
79 VOID umss_fix_sff_result(PIO_PACKET io_packet, SCSI_REQUEST_BLOCK * srb);
80
81 PDEVICE_OBJECT
82 umss_create_port_device(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdriver)
83 {
84
85 // currently a port device is a connection point
86 // and upper driver use this to register itself
87 // with umss driver for future notification of
88 // pnp event. 2004-03-22 23:12:41
89 CHAR dev_name[64];
90 STRING string;
91 NTSTATUS status;
92 PDEVICE_OBJECT pdev;
93 UNICODE_STRING name_string, symb_link;
94 PUMSS_PORT_DEV_EXT pdev_ext;
95
96 sprintf(dev_name, "\\Device\\usbPort_%d", (int)0);
97
98 RtlInitString(&string, dev_name);
99 RtlAnsiStringToUnicodeString(&name_string, &string, TRUE);
100 pdev = NULL;
101
102 status = IoCreateDevice(dev_mgr->usb_driver_obj,
103 sizeof(UMSS_PORT_DEV_EXT), &name_string, FILE_USB_DEV_TYPE, 0, TRUE, &pdev);
104
105 if (status == STATUS_SUCCESS)
106 {
107 //
108 // We do buffered io
109 //
110 pdev->Flags |= DO_BUFFERED_IO;
111
112 pdev->Flags &= ~DO_DEVICE_INITIALIZING;
113 pdev->StackSize = 2; //one for fdo, one for file device obj
114
115 pdev_ext = (PUMSS_PORT_DEV_EXT) pdev->DeviceExtension;
116
117 pdev_ext->dev_ext_hdr.type = NTDEV_TYPE_CLIENT_DEV;
118 pdev_ext->dev_ext_hdr.dispatch = umss_port_dispatch_routine;
119 pdev_ext->dev_ext_hdr.start_io = NULL;
120 pdev_ext->dev_ext_hdr.dev_mgr = dev_mgr;
121 pdev_ext->pdriver = pdriver;
122
123 sprintf(dev_name, "\\DosDevices\\usbPort%d", (int)0);
124
125 RtlInitString(&string, dev_name);
126 RtlAnsiStringToUnicodeString(&symb_link, &string, TRUE);
127 IoCreateSymbolicLink(&symb_link, &name_string);
128 RtlFreeUnicodeString(&symb_link);
129
130 }
131
132 RtlFreeUnicodeString(&name_string);
133 return pdev;
134 }
135
136 BOOLEAN
137 umss_delete_port_device(PDEVICE_OBJECT dev_obj)
138 {
139 CHAR dev_name[64];
140 STRING string;
141 UNICODE_STRING symb_link;
142
143 if (dev_obj == NULL)
144 return FALSE;
145
146 // remove the symbolic link
147 sprintf(dev_name, "\\DosDevices\\usbPort%d", (int)0);
148 RtlInitString(&string, dev_name);
149 RtlAnsiStringToUnicodeString(&symb_link, &string, TRUE);
150 IoDeleteSymbolicLink(&symb_link);
151 RtlFreeUnicodeString(&symb_link);
152
153 if (dev_obj->ReferenceCount == 0)
154 {
155 IoDeleteDevice(dev_obj);
156 usb_dbg_print(DBGLVL_MAXIMUM, ("umss_delete_port_device(): port device object is removed\n"));
157 }
158 return TRUE;
159 }
160
161 // FIXME!!! there can not be sent IOCTL_SUBMIT_URB_XXX while
162 // the IOCTL_SUBMIT_CDB_XXX are active. may confuse the device.
163 // not resolved yet.
164 // 2004-03-22 23:12:26
165 NTSTATUS
166 umss_port_dispatch_routine(PDEVICE_OBJECT pdev_obj, PIRP irp)
167 {
168 ULONG ctrl_code;
169 NTSTATUS status;
170 PIO_STACK_LOCATION irp_stack;
171 PUMSS_PORT_DEV_EXT pdev_ext;
172 PUMSS_DRVR_EXTENSION pdrvr_ext;
173
174 if (pdev_obj == NULL || irp == NULL)
175 return STATUS_INVALID_PARAMETER;
176
177 status = STATUS_SUCCESS;
178 irp_stack = IoGetCurrentIrpStackLocation(irp);
179 ctrl_code = irp_stack->Parameters.DeviceIoControl.IoControlCode;
180
181 pdev_ext = (PUMSS_PORT_DEV_EXT) pdev_obj->DeviceExtension;
182
183 switch (irp_stack->MajorFunction)
184 {
185 case IRP_MJ_INTERNAL_DEVICE_CONTROL:
186 {
187 switch (ctrl_code)
188 {
189 case IOCTL_REGISTER_DRIVER:
190 {
191 PCLASS_DRV_REG_INFO pcdri;
192 if (irp_stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(CLASS_DRV_REG_INFO))
193 {
194 EXIT_DISPATCH(STATUS_INVALID_PARAMETER, irp);
195 }
196
197 pcdri = irp->AssociatedIrp.SystemBuffer;
198 if (pcdri->fdo_driver == NULL || pcdri->add_device == NULL || pcdri->pnp_dispatch == NULL)
199 {
200 EXIT_DISPATCH(STATUS_INVALID_PARAMETER, irp);
201 }
202 pdrvr_ext = (PUMSS_DRVR_EXTENSION) pdev_ext->pdriver->driver_ext;
203 pdrvr_ext->class_driver_info.fdo_driver = pcdri->fdo_driver;
204 pdrvr_ext->class_driver_info.add_device = pcdri->add_device;
205 pdrvr_ext->class_driver_info.pnp_dispatch = pcdri->pnp_dispatch;
206 EXIT_DISPATCH(STATUS_SUCCESS, irp);
207 }
208 case IOCTL_REVOKE_DRIVER:
209 {
210 pdrvr_ext = (PUMSS_DRVR_EXTENSION) pdev_ext->pdriver->driver_ext;
211 pdrvr_ext->class_driver_info.fdo_driver = NULL;
212 pdrvr_ext->class_driver_info.add_device = NULL;
213 pdrvr_ext->class_driver_info.pnp_dispatch = NULL;
214 EXIT_DISPATCH(STATUS_SUCCESS, irp);
215 }
216 }
217 }
218 case IRP_MJ_CREATE:
219 case IRP_MJ_CLOSE:
220 {
221 EXIT_DISPATCH(STATUS_SUCCESS, irp);
222 }
223 }
224 EXIT_DISPATCH(STATUS_INVALID_DEVICE_REQUEST, irp);
225 }
226
227 BOOLEAN
228 umss_driver_init(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdriver)
229 {
230 PUMSS_DRVR_EXTENSION pdrvr_ext;
231
232 if (dev_mgr == NULL || pdriver == NULL)
233 return FALSE;
234
235 //init driver structure, no PNP table functions
236 pdriver->driver_desc.flags = USB_DRIVER_FLAG_DEV_CAPABLE;
237 pdriver->driver_desc.vendor_id = 0x0dd8; // USB Vendor ID
238 pdriver->driver_desc.product_id = 0x0003; // USB Product ID.
239 pdriver->driver_desc.release_num = 0x100; // Release Number of Device
240
241 pdriver->driver_desc.config_val = 1; // Configuration Value
242 pdriver->driver_desc.if_num = 1; // Interface Number
243 pdriver->driver_desc.if_class = USB_CLASS_MASS_STORAGE; // Interface Class
244 pdriver->driver_desc.if_sub_class = 0; // Interface SubClass
245 pdriver->driver_desc.if_protocol = 0; // Interface Protocol
246
247 pdriver->driver_desc.driver_name = "USB Mass Storage driver"; // Driver name for Name Registry
248 pdriver->driver_desc.dev_class = USB_CLASS_MASS_STORAGE;
249 pdriver->driver_desc.dev_sub_class = 0; // Device Subclass
250 pdriver->driver_desc.dev_protocol = 0; // Protocol Info.
251
252 pdriver->driver_ext = usb_alloc_mem(NonPagedPool, sizeof(UMSS_DRVR_EXTENSION));
253 if (!pdriver->driver_ext) return FALSE;
254 pdriver->driver_ext_size = sizeof(UMSS_DRVR_EXTENSION);
255
256 RtlZeroMemory(pdriver->driver_ext, sizeof(UMSS_DRVR_EXTENSION));
257 pdrvr_ext = (PUMSS_DRVR_EXTENSION) pdriver->driver_ext;
258 pdrvr_ext->dev_count = 0;
259 InitializeListHead(&pdrvr_ext->dev_list);
260 ExInitializeFastMutex(&pdrvr_ext->dev_list_mutex);
261
262 pdriver->disp_tbl.version = 1;
263 pdriver->disp_tbl.dev_connect = umss_connect;
264 pdriver->disp_tbl.dev_disconnect = umss_disconnect;
265 pdriver->disp_tbl.dev_stop = umss_stop;
266 pdriver->disp_tbl.dev_reserved = NULL;
267
268 if ((pdrvr_ext->port_dev_obj = umss_create_port_device(dev_mgr, pdriver)) == NULL)
269 {
270 usb_free_mem(pdriver->driver_ext);
271 pdriver->driver_ext = NULL;
272 pdriver->driver_ext_size = 0;
273 pdriver->disp_tbl.dev_connect = NULL;
274 pdriver->disp_tbl.dev_stop = NULL;
275 pdriver->disp_tbl.dev_disconnect = NULL;
276 return FALSE;
277 }
278
279 umss_load_class_driver(NULL);
280
281 // umss_schedule_workitem( NULL, umss_load_class_driver, NULL, 0 );
282 usb_dbg_print(DBGLVL_MAXIMUM, ("umss_driver_init(): umss driver is initialized\n"));
283 return TRUE;
284 }
285
286 BOOLEAN
287 umss_driver_destroy(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdriver)
288 {
289 PUMSS_DRVR_EXTENSION pdrvr_ext;
290 if (dev_mgr == NULL || pdriver == NULL)
291 return FALSE;
292
293 pdrvr_ext = (PUMSS_DRVR_EXTENSION) pdriver->driver_ext;
294 umss_delete_port_device(pdrvr_ext->port_dev_obj);
295 pdrvr_ext->port_dev_obj = NULL;
296
297 ASSERT(IsListEmpty(&pdrvr_ext->dev_list) == TRUE);
298 usb_free_mem(pdriver->driver_ext);
299 pdriver->driver_ext = NULL;
300 pdriver->driver_ext_size = 0;
301 usb_dbg_print(DBGLVL_MAXIMUM, ("umss_driver_destroy(): umss driver is destroyed\n"));
302 return TRUE;
303 }
304
305 PDEVICE_OBJECT
306 umss_create_device(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER umss_drvr, DEV_HANDLE dev_handle, BOOLEAN is_if)
307 {
308
309 CHAR dev_name[64], dev_id;
310 STRING string;
311 NTSTATUS status;
312 PDEVICE_OBJECT pdev;
313 UNICODE_STRING name_string, symb_link;
314 PUMSS_DRVR_EXTENSION pdrvr_ext;
315 PUMSS_DEVICE_EXTENSION pdev_ext;
316
317 usb_dbg_print(DBGLVL_MAXIMUM, ("umss_create_device(): entering...\n"));
318 pdrvr_ext = (PUMSS_DRVR_EXTENSION) umss_drvr->driver_ext;
319 dev_id = (UCHAR) dev_id_from_handle(dev_handle); // pdrvr_ext->dev_count;
320
321 if (is_if == FALSE)
322 sprintf(dev_name, "\\Device\\umssdev_%d", (int)dev_id);
323 else
324 sprintf(dev_name, "\\Device\\umssifdev_%d", (int)dev_id);
325
326 RtlInitString(&string, dev_name);
327 RtlAnsiStringToUnicodeString(&name_string, &string, TRUE);
328 pdev = NULL;
329
330 status = IoCreateDevice(dev_mgr->usb_driver_obj,
331 sizeof(UMSS_DEVICE_EXTENSION),
332 &name_string,
333 FILE_USB_DEV_TYPE,
334 0,
335 TRUE,
336 &pdev);
337
338 if (status == STATUS_SUCCESS)
339 {
340 //
341 // We do direct io
342 //
343 pdev->Flags |= DO_DIRECT_IO;
344
345 pdev->Flags &= ~DO_DEVICE_INITIALIZING;
346 pdev->StackSize = 2; //one for fdo, one for file device obj
347
348 pdev_ext = (PUMSS_DEVICE_EXTENSION) pdev->DeviceExtension;
349
350 //may be accessed by other thread
351 ExAcquireFastMutex(&pdrvr_ext->dev_list_mutex);
352 InsertTailList(&pdrvr_ext->dev_list, &pdev_ext->dev_obj_link);
353 pdrvr_ext->dev_count++;
354 ExReleaseFastMutex(&pdrvr_ext->dev_list_mutex);
355
356 if (is_if)
357 pdev_ext->flags |= UMSS_DEV_FLAG_IF_DEV;
358
359 pdev_ext->umss_dev_id = dev_id;
360 pdev_ext->pdo = pdev;
361 pdev_ext->dev_handle = dev_handle;
362 pdev_ext->dev_mgr = dev_mgr;
363 pdev_ext->pdriver = umss_drvr;
364
365 pdev_ext->dev_ext_hdr.type = NTDEV_TYPE_CLIENT_DEV;
366 pdev_ext->dev_ext_hdr.dispatch = umss_dispatch_routine;
367 pdev_ext->dev_ext_hdr.start_io = umss_start_io;
368 pdev_ext->dev_ext_hdr.dev_mgr = dev_mgr;
369
370 if (is_if == FALSE)
371 sprintf(dev_name, "\\DosDevices\\umssdev%d", (int)dev_id);
372 else
373 sprintf(dev_name, "\\DosDevices\\umssifdev%d", (int)dev_id);
374
375 RtlInitString(&string, dev_name);
376 RtlAnsiStringToUnicodeString(&symb_link, &string, TRUE);
377 IoCreateSymbolicLink(&symb_link, &name_string);
378 RtlFreeUnicodeString(&symb_link);
379 KeInitializeEvent(&pdev_ext->sync_event, SynchronizationEvent, FALSE);
380 KeInitializeSpinLock(&pdev_ext->dev_lock);
381
382 }
383 RtlFreeUnicodeString(&name_string);
384 return pdev;
385 }
386
387 BOOLEAN
388 umss_connect(PDEV_CONNECT_DATA param, DEV_HANDLE dev_handle)
389 {
390 PURB purb;
391 NTSTATUS status;
392 PUSB_CTRL_SETUP_PACKET psetup;
393 PUSB_DEV_MANAGER dev_mgr;
394 PUSB_DRIVER pdrvr;
395
396 usb_dbg_print(DBGLVL_MAXIMUM, ("umss_connect(): entering...\n"));
397
398 dev_mgr = param->dev_mgr;
399 pdrvr = param->pdriver;
400
401 //directly set the configuration
402 purb = usb_alloc_mem(NonPagedPool, sizeof(URB));
403 if (purb == NULL)
404 return FALSE;
405
406 psetup = (PUSB_CTRL_SETUP_PACKET) (purb)->setup_packet;
407 urb_init((purb));
408
409 purb->endp_handle = dev_handle | 0xffff;
410 purb->data_buffer = NULL;
411 purb->data_length = 0;
412 purb->completion = umss_set_cfg_completion;
413 purb->context = dev_mgr;
414 purb->reference = (LONG) pdrvr;
415 psetup->bmRequestType = 0;
416 psetup->bRequest = USB_REQ_SET_CONFIGURATION;
417 psetup->wValue = 1;
418 psetup->wIndex = 0;
419 psetup->wLength = 0;
420
421 status = usb_submit_urb(dev_mgr, purb);
422 if (status != STATUS_PENDING)
423 {
424 usb_free_mem(purb);
425 return FALSE;
426 }
427 return TRUE;
428 }
429
430 VOID
431 umss_set_cfg_completion(PURB purb, PVOID pcontext)
432 {
433 PUSB_CTRL_SETUP_PACKET psetup;
434 PUCHAR buf;
435 PWORK_QUEUE_ITEM pwork_item;
436 PUMSS_CREATE_DATA pcd;
437 DEV_HANDLE dev_handle;
438 NTSTATUS status;
439 PUSB_DEV_MANAGER dev_mgr;
440 PUSB_DRIVER pdrvr;
441
442 if (purb == NULL || pcontext == NULL)
443 return;
444
445 dev_mgr = (PUSB_DEV_MANAGER) pcontext;
446 pdrvr = (PUSB_DRIVER) purb->reference;
447 dev_handle = purb->endp_handle & ~0xffff;
448
449
450 if (purb->status != STATUS_SUCCESS)
451 {
452 usb_free_mem(purb);
453 return;
454 }
455
456 buf = usb_alloc_mem(NonPagedPool, 512);
457 if (buf == NULL)
458 {
459 usb_free_mem(purb);
460 return;
461 }
462
463 //now let's get the descs, one configuration, one interface and two endpoint
464 psetup = (PUSB_CTRL_SETUP_PACKET) (purb)->setup_packet;
465 purb->data_buffer = buf;
466 purb->data_length = 512;
467 purb->completion = NULL; //this is an immediate request, no needs completion
468 purb->context = dev_mgr;
469 purb->reference = 0;
470 psetup->bmRequestType = 0x80;
471 psetup->bRequest = USB_REQ_GET_DESCRIPTOR;
472 psetup->wValue = USB_DT_CONFIG << 8;
473 psetup->wIndex = 0;
474 psetup->wLength = 512;
475
476 status = usb_submit_urb(dev_mgr, purb);
477 if (status == STATUS_PENDING)
478 {
479 TRAP();
480 }
481 usb_free_mem(purb);
482 purb = NULL;
483
484 if (status != STATUS_SUCCESS)
485 {
486 usb_free_mem(buf);
487 buf = NULL;
488 return;
489 }
490
491 pcd = usb_alloc_mem(NonPagedPool, sizeof(WORK_QUEUE_ITEM) + sizeof(UMSS_CREATE_DATA));
492 if (pcd == NULL)
493 {
494 usb_free_mem(buf);
495 buf = NULL;
496 return;
497 }
498
499 pcd->desc_buf = buf;
500 pcd->dev_handle = dev_handle;
501 pcd->dev_mgr = dev_mgr;
502 pcd->pdriver = pdrvr;
503 pwork_item = (PWORK_QUEUE_ITEM) (&pcd[1]);
504
505 ExInitializeWorkItem(pwork_item, umss_start_create_device, (PVOID) pcd);
506 ExQueueWorkItem(pwork_item, DelayedWorkQueue);
507 }
508
509 VOID NTAPI
510 umss_start_create_device(IN PVOID Parameter)
511 {
512 LONG i;
513 PUCHAR desc_buf;
514 NTSTATUS status;
515 PUSB_DEV pdev;
516 DEV_HANDLE dev_handle;
517 PUSB_DRIVER pdrvr;
518 PDEVICE_OBJECT pdev_obj;
519 PUSB_DEV_MANAGER dev_mgr;
520 PUMSS_CREATE_DATA pcd;
521 PUSB_INTERFACE_DESC pif_desc;
522 PUSB_ENDPOINT_DESC pendp_desc;
523 PUMSS_DEVICE_EXTENSION pdev_ext;
524 PUSB_CONFIGURATION_DESC pconfig_desc;
525
526 USE_BASIC_NON_PENDING_IRQL;
527
528 if (Parameter == NULL)
529 return;
530
531 pcd = (PUMSS_CREATE_DATA) Parameter;
532 desc_buf = pcd->desc_buf;
533 dev_mgr = pcd->dev_mgr;
534 dev_handle = pcd->dev_handle;
535 pdrvr = pcd->pdriver;
536 usb_free_mem(pcd);
537 pcd = NULL;
538
539 status = usb_query_and_lock_dev(dev_mgr, dev_handle, &pdev);
540 if (status != STATUS_SUCCESS)
541 {
542 usb_free_mem(desc_buf);
543 return;
544 }
545
546 pdev_obj = umss_create_device(dev_mgr, pdrvr, dev_handle, FALSE);
547
548 lock_dev(pdev, FALSE);
549 if (pdev_obj == NULL ||
550 dev_state(pdev) == USB_DEV_STATE_ZOMB ||
551 dev_mgr_set_driver(dev_mgr, dev_handle, pdrvr, pdev) == FALSE)
552 {
553 usb_free_mem(desc_buf);
554 unlock_dev(pdev, FALSE);
555
556 if (pdev_obj)
557 umss_delete_device(dev_mgr, pdrvr, pdev_obj, FALSE);
558
559 usb_unlock_dev(pdev);
560 return;
561 }
562 unlock_dev(pdev, FALSE);
563
564 pdev_ext = (PUMSS_DEVICE_EXTENSION) pdev_obj->DeviceExtension;
565
566 pdev_ext->desc_buf = desc_buf;
567 pdev_ext->pif_desc = NULL;
568 pdev_ext->pin_endp_desc = pdev_ext->pout_endp_desc = NULL;
569
570 pconfig_desc = (PUSB_CONFIGURATION_DESC) desc_buf;
571 pif_desc = (PUSB_INTERFACE_DESC) (&pconfig_desc[1]);
572 //search for our if
573 for(i = 0; ((UCHAR) i) < pconfig_desc->bNumInterfaces; i++)
574 {
575 if (pif_desc->bLength == sizeof(USB_INTERFACE_DESC) && pif_desc->bDescriptorType == USB_DT_INTERFACE)
576 {
577 if (pif_desc->bInterfaceClass == USB_CLASS_MASS_STORAGE)
578 {
579 pdev_ext->pif_desc = pif_desc;
580 pdev_ext->if_idx = (UCHAR) i;
581 break;
582 }
583 else
584 {
585 if (usb_skip_if_and_altif((PUCHAR *) & pif_desc) == FALSE)
586 break;
587 }
588 }
589 else
590 {
591 break;
592 }
593 }
594
595 if (pdev_ext->pif_desc)
596 {
597 pendp_desc = (PUSB_ENDPOINT_DESC) & pif_desc[1];
598 for(i = 0; ((UCHAR) i) < pif_desc->bNumEndpoints; i++)
599 {
600 if (pendp_desc->bDescriptorType == USB_DT_ENDPOINT
601 && pendp_desc->bLength == sizeof(USB_ENDPOINT_DESC))
602 {
603 if ((pendp_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)
604 {
605 pdev_ext->pint_endp_desc = pendp_desc;
606 pdev_ext->int_endp_idx = (UCHAR) i;
607 }
608 else if ((pendp_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK)
609 {
610 if (pendp_desc->bEndpointAddress & USB_DIR_IN)
611 {
612 pdev_ext->pin_endp_desc = pendp_desc;
613 pdev_ext->in_endp_idx = (UCHAR) i;
614 }
615 else
616 {
617 pdev_ext->pout_endp_desc = pendp_desc;
618 pdev_ext->out_endp_idx = (UCHAR) i;
619 }
620 }
621 pendp_desc = &pendp_desc[1];
622 }
623 else
624 break;
625 }
626 }
627 usb_unlock_dev(pdev);
628 return;
629 }
630
631 BOOLEAN
632 umss_stop(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle)
633 {
634 UNREFERENCED_PARAMETER(dev_handle);
635 UNREFERENCED_PARAMETER(dev_mgr);
636 return TRUE;
637 }
638
639 BOOLEAN
640 umss_disconnect(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle)
641 {
642 PDEVICE_OBJECT dev_obj;
643 NTSTATUS status;
644 PUSB_DEV pdev;
645 PUSB_DRIVER pdrvr;
646
647 if (dev_mgr == NULL || dev_handle == 0)
648 return FALSE;
649
650 pdev = NULL;
651 //special use of the lock dev, simply use this routine to get the dev
652 status = usb_query_and_lock_dev(dev_mgr, dev_handle, &pdev);
653 if (pdev == NULL)
654 {
655 return FALSE;
656 }
657 if (status == STATUS_SUCCESS)
658 {
659 // must be a bug
660 TRAP();
661 usb_unlock_dev(pdev);
662 }
663 pdrvr = pdev->dev_driver;
664 dev_obj = pdev->dev_obj;
665 pdev = NULL;
666
667 return umss_delete_device(dev_mgr, pdrvr, dev_obj, FALSE);
668 }
669
670 VOID
671 umss_deferred_delete_device(PVOID context)
672 {
673 PDEVICE_OBJECT dev_obj;
674 PUMSS_DEVICE_EXTENSION pdev_ext;
675 PUMSS_DRVR_EXTENSION pdrvr_ext;
676 LARGE_INTEGER interval;
677
678 if (context == NULL)
679 return;
680
681 dev_obj = (PDEVICE_OBJECT) context;
682 pdev_ext = dev_obj->DeviceExtension;
683 pdrvr_ext = (PUMSS_DRVR_EXTENSION) pdev_ext->pdriver->driver_ext;
684
685 interval.QuadPart = -20000; //two ms
686
687 for(;;)
688 {
689 if (dev_obj->ReferenceCount)
690 KeDelayExecutionThread(KernelMode, TRUE, &interval);
691 else
692 {
693 KeDelayExecutionThread(KernelMode, TRUE, &interval);
694 if (dev_obj->ReferenceCount == 0)
695 break;
696 }
697 }
698 usb_dbg_print(DBGLVL_MAXIMUM, ("umss_deferred_delete_device(): delete device, 0x%x\n", dev_obj));
699
700 ExAcquireFastMutex(&pdrvr_ext->dev_list_mutex);
701 RemoveEntryList(&pdev_ext->dev_obj_link);
702 pdrvr_ext->dev_count--;
703 ExReleaseFastMutex(&pdrvr_ext->dev_list_mutex);
704
705 IoDeleteDevice(dev_obj);
706 return;
707 }
708
709 BOOLEAN
710 umss_delete_device(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdrvr, PDEVICE_OBJECT dev_obj, BOOLEAN is_if)
711 {
712 CHAR dev_name[64];
713 STRING string;
714 UNICODE_STRING symb_link;
715 PUMSS_DEVICE_EXTENSION pdev_ext;
716 PUMSS_DRVR_EXTENSION pdrvr_ext;
717
718 if (dev_obj == NULL)
719 return FALSE;
720
721 if (pdrvr == NULL || dev_mgr == NULL)
722 return FALSE;
723
724 pdev_ext = (PUMSS_DEVICE_EXTENSION) dev_obj->DeviceExtension;
725 pdrvr_ext = (PUMSS_DRVR_EXTENSION) pdrvr->driver_ext;
726 if (is_if == FALSE)
727 sprintf(dev_name, "\\DosDevices\\umssdev%d", (int)pdev_ext->umss_dev_id);
728 else
729 sprintf(dev_name, "\\DosDevices\\umssifdev%d", (int)pdev_ext->umss_dev_id);
730
731 RtlInitString(&string, dev_name);
732 RtlAnsiStringToUnicodeString(&symb_link, &string, TRUE);
733 IoDeleteSymbolicLink(&symb_link);
734 RtlFreeUnicodeString(&symb_link);
735
736 if (pdev_ext->desc_buf)
737 {
738 usb_dbg_print(DBGLVL_MAXIMUM, ("umss_delete_device(): delete desc_buf\n"));
739 usb_free_mem(pdev_ext->desc_buf);
740 pdev_ext->desc_buf = NULL;
741
742 }
743
744 if (dev_obj->ReferenceCount == 0)
745 {
746 ExAcquireFastMutex(&pdrvr_ext->dev_list_mutex);
747 RemoveEntryList(&pdev_ext->dev_obj_link);
748 pdrvr_ext->dev_count--;
749 ExReleaseFastMutex(&pdrvr_ext->dev_list_mutex);
750
751 IoDeleteDevice(dev_obj);
752 return TRUE;
753 }
754
755 //
756 // FIXME: how if the driver unloading happens
757 // since this is called in dev_mgr_disconnect_dev, umss_schedule_workitem
758 // can not protect the USB_DEV object from be deleted. so the workitem
759 // can not access anything relative to the USB_DEV object. In this case
760 // we will tollerate the usb_query_and_lock_dev failure since it will
761 // never success when come to this point, and we won't pass dev_mgr
762 // and pdev to the function. But other scenarios, usb_query_and_lock_dev
763 // can not fail if dev_mgr and pdev are passed valid.
764 // When driver is unloading, don't know. Wish NT will unload the driver
765 // only when all the devices to the driver are deleted.
766 //
767 umss_schedule_workitem(dev_obj, umss_deferred_delete_device, NULL, 0);
768 return TRUE;
769 }
770
771 VOID
772 umss_submit_io_packet(PDEVICE_OBJECT dev_obj, PIO_PACKET io_packet)
773 {
774 NTSTATUS status;
775 PUMSS_DEVICE_EXTENSION pdev_ext;
776 PUSB_DEV pdev;
777
778 pdev_ext = dev_obj->DeviceExtension;
779
780 // lock the dev, the pdev_ext->pif_desc won't go away.
781 if ((status = usb_query_and_lock_dev(pdev_ext->dev_mgr, pdev_ext->dev_handle, &pdev)) != STATUS_SUCCESS)
782 {
783 usb_dbg_print(DBGLVL_MAXIMUM, ("umss_start_io(): error, device is not valid\n"));
784 UMSS_COMPLETE_START_IO(dev_obj, status, io_packet->pirp);
785 return;
786 }
787
788 if (pdev_ext->pif_desc->bInterfaceProtocol == PROTOCOL_BULKONLY)
789 {
790 status = umss_bulkonly_startio(pdev_ext, io_packet);
791 }
792 else if (pdev_ext->pif_desc->bInterfaceProtocol == PROTOCOL_CB
793 || pdev_ext->pif_desc->bInterfaceProtocol == PROTOCOL_CBI)
794 {
795 status = umss_cbi_startio(pdev_ext, io_packet);
796 }
797 else
798 {
799 status = STATUS_DEVICE_PROTOCOL_ERROR;
800 }
801 usb_unlock_dev(pdev);
802 UMSS_COMPLETE_START_IO(dev_obj, status, io_packet->pirp);
803 return;
804 }
805
806 VOID
807 NTAPI
808 umss_start_io(IN PDEVICE_OBJECT dev_obj, IN PIRP irp)
809 {
810 ULONG ctrl_code;
811 NTSTATUS status;
812 PIO_STACK_LOCATION irp_stack;
813 PUMSS_DEVICE_EXTENSION pdev_ext;
814 IO_PACKET io_packet;
815 PUSER_IO_PACKET user_io_packet;
816
817 if (dev_obj == NULL || irp == NULL)
818 return;
819
820 status = STATUS_SUCCESS;
821
822 irp_stack = IoGetCurrentIrpStackLocation(irp);
823 ctrl_code = irp_stack->Parameters.DeviceIoControl.IoControlCode;
824 pdev_ext = (PUMSS_DEVICE_EXTENSION) dev_obj->DeviceExtension;
825
826 if (irp_stack->MajorFunction == IRP_MJ_SCSI)
827 {
828 umss_process_srb(dev_obj, irp);
829 return;
830 }
831
832 if (irp_stack->MajorFunction != IRP_MJ_DEVICE_CONTROL)
833 {
834 UMSS_COMPLETE_START_IO(dev_obj, STATUS_INVALID_DEVICE_REQUEST, irp);
835 }
836
837 switch (ctrl_code)
838 {
839 case IOCTL_UMSS_SUBMIT_CDB_IN:
840 case IOCTL_UMSS_SUBMIT_CDB_OUT:
841 case IOCTL_UMSS_SUBMIT_CDB:
842 {
843 if (irp_stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(USER_IO_PACKET))
844 {
845 UMSS_COMPLETE_START_IO(dev_obj, STATUS_INVALID_PARAMETER, irp);
846 }
847
848 user_io_packet = (PUSER_IO_PACKET) irp->AssociatedIrp.SystemBuffer;
849
850 if (user_io_packet->sub_class != pdev_ext->pif_desc->bInterfaceSubClass)
851 {
852 // not agree with the dev's subclass
853 UMSS_COMPLETE_START_IO(dev_obj, STATUS_DEVICE_PROTOCOL_ERROR, irp);
854 }
855
856 RtlZeroMemory(&io_packet, sizeof(io_packet));
857 io_packet.cdb_length = user_io_packet->cdb_length;
858 io_packet.lun = user_io_packet->lun;
859
860 RtlCopyMemory(io_packet.cdb, user_io_packet->cdb, MAX_CDB_LENGTH);
861
862 if (ctrl_code == IOCTL_UMSS_SUBMIT_CDB_IN)
863 io_packet.flags |= USB_DIR_IN;
864
865 if (ctrl_code != IOCTL_UMSS_SUBMIT_CDB)
866 {
867 if (irp_stack->Parameters.DeviceIoControl.OutputBufferLength == 0)
868 UMSS_COMPLETE_START_IO(dev_obj, STATUS_BUFFER_TOO_SMALL, irp);
869
870 io_packet.data_buffer = MmGetSystemAddressForMdl(irp->MdlAddress);
871 io_packet.data_length = irp_stack->Parameters.DeviceIoControl.OutputBufferLength;
872
873 if (io_packet.data_length > MAX_BULK_TRANSFER_LENGTH)
874 UMSS_COMPLETE_START_IO(dev_obj, STATUS_BUFFER_TOO_SMALL, irp);
875
876 //synchronize the buffer
877 if (io_packet.flags & USB_DIR_IN)
878 KeFlushIoBuffers(irp->MdlAddress, TRUE, TRUE);
879 else
880 KeFlushIoBuffers(irp->MdlAddress, FALSE, TRUE);
881 }
882
883 io_packet.pirp = irp;
884 umss_submit_io_packet(dev_obj, &io_packet);
885 return;
886 }
887 case IOCTL_SCSI_PASS_THROUGH:
888 {
889 PSCSI_PASS_THROUGH pass_through;
890 IO_PACKET io_packet;
891
892 pass_through = irp->AssociatedIrp.SystemBuffer;
893
894 if (pass_through->DataTransferLength &&
895 pass_through->DataBufferOffset != sizeof(SCSI_PASS_THROUGH))
896 UMSS_COMPLETE_START_IO(dev_obj, STATUS_INVALID_PARAMETER, irp);
897
898 if (pass_through->SenseInfoLength &&
899 (pass_through->SenseInfoOffset !=
900 pass_through->DataBufferOffset + pass_through->DataTransferLength))
901 UMSS_COMPLETE_START_IO(dev_obj, STATUS_INVALID_PARAMETER, irp);
902
903 if (irp_stack->Parameters.DeviceIoControl.InputBufferLength <
904 (sizeof(SCSI_PASS_THROUGH) +
905 pass_through->SenseInfoLength + pass_through->DataTransferLength))
906 UMSS_COMPLETE_START_IO(dev_obj, STATUS_BUFFER_TOO_SMALL, irp);
907
908 RtlZeroMemory(&io_packet, sizeof(io_packet));
909
910 io_packet.flags |= IOP_FLAG_SCSI_CTRL_TRANSFER;
911 if (pass_through->DataIn)
912 io_packet.flags |= IOP_FLAG_DIR_IN;
913
914 io_packet.data_buffer = (PVOID) & pass_through[1];
915 io_packet.data_length = pass_through->DataTransferLength;
916
917 if (pass_through->SenseInfoLength)
918 {
919 io_packet.sense_data = ((PUCHAR) pass_through) + pass_through->SenseInfoOffset;
920 io_packet.sense_data_length = pass_through->SenseInfoLength;
921 io_packet.flags |= IOP_FLAG_REQ_SENSE;
922 }
923
924 io_packet.cdb_length = pass_through->CdbLength;
925 RtlCopyMemory(io_packet.cdb, pass_through->Cdb, sizeof(io_packet.cdb));
926 io_packet.lun = 0;
927 io_packet.pirp = irp;
928 umss_submit_io_packet(dev_obj, &io_packet);
929 return;
930 }
931 case IOCTL_SCSI_PASS_THROUGH_DIRECT:
932 {
933 PSCSI_PASS_THROUGH_DIRECT pass_through_direct;
934 IO_PACKET io_packet;
935
936 pass_through_direct = irp->AssociatedIrp.SystemBuffer;
937
938 if (pass_through_direct->SenseInfoLength &&
939 pass_through_direct->SenseInfoOffset != sizeof(SCSI_PASS_THROUGH_DIRECT))
940 UMSS_COMPLETE_START_IO(dev_obj, STATUS_INVALID_PARAMETER, irp);
941
942 if (irp_stack->Parameters.DeviceIoControl.InputBufferLength <
943 sizeof(SCSI_PASS_THROUGH_DIRECT) + pass_through_direct->SenseInfoLength)
944 UMSS_COMPLETE_START_IO(dev_obj, STATUS_BUFFER_TOO_SMALL, irp);
945
946 RtlZeroMemory(&io_packet, sizeof(io_packet));
947
948 io_packet.flags |= IOP_FLAG_SCSI_CTRL_TRANSFER;
949 if (pass_through_direct->DataIn)
950 io_packet.flags |= IOP_FLAG_DIR_IN;
951
952 io_packet.data_buffer = pass_through_direct->DataBuffer;
953 io_packet.data_length = pass_through_direct->DataTransferLength;
954
955 if (pass_through_direct->SenseInfoLength)
956 {
957 io_packet.sense_data = ((PUCHAR) pass_through_direct) + pass_through_direct->SenseInfoOffset;
958 io_packet.sense_data_length = pass_through_direct->SenseInfoLength;
959 io_packet.flags |= IOP_FLAG_REQ_SENSE;
960 }
961
962 io_packet.cdb_length = pass_through_direct->CdbLength;
963 RtlCopyMemory(io_packet.cdb, pass_through_direct->Cdb, sizeof(io_packet.cdb));
964 io_packet.lun = 0;
965 io_packet.pirp = irp;
966 umss_submit_io_packet(dev_obj, &io_packet);
967 return;
968 }
969 case IOCTL_SUBMIT_URB_RD:
970 case IOCTL_SUBMIT_URB_NOIO:
971 case IOCTL_SUBMIT_URB_WR:
972 {
973 gendrv_startio(dev_obj, irp);
974 return;
975 }
976 default:
977 UMSS_COMPLETE_START_IO(dev_obj, STATUS_INVALID_DEVICE_REQUEST, irp);
978 }
979 return;
980 }
981
982 // bugbug!!! there can not be sent IOCTL_SUBMIT_URB_XXX while
983 // the IOCTL_SUBMIT_CDB_XXX are active. may confuse the device.
984 // not resolved yet.
985 NTSTATUS
986 umss_dispatch_routine(PDEVICE_OBJECT pdev_obj, PIRP irp)
987 {
988 ULONG ctrl_code;
989 NTSTATUS status;
990 PIO_STACK_LOCATION irp_stack;
991 PUMSS_DEVICE_EXTENSION pdev_ext;
992 USE_BASIC_NON_PENDING_IRQL;
993
994 if (pdev_obj == NULL || irp == NULL)
995 return STATUS_INVALID_PARAMETER;
996
997 status = STATUS_SUCCESS;
998 irp_stack = IoGetCurrentIrpStackLocation(irp);
999 ctrl_code = irp_stack->Parameters.DeviceIoControl.IoControlCode;
1000
1001 pdev_ext = (PUMSS_DEVICE_EXTENSION) pdev_obj->DeviceExtension;
1002
1003 switch (irp_stack->MajorFunction)
1004 {
1005 case IRP_MJ_CREATE:
1006 case IRP_MJ_CLOSE:
1007 {
1008 return dev_mgr_dispatch(pdev_ext->dev_mgr, irp);
1009 }
1010 case IRP_MJ_INTERNAL_DEVICE_CONTROL:
1011 {
1012 // function code to receive scsi request
1013 UMSS_EXIT_DISPATCH(pdev_obj, STATUS_PENDING, irp);
1014 }
1015 case IRP_MJ_DEVICE_CONTROL:
1016 {
1017 switch (ctrl_code)
1018 {
1019 case IOCTL_UMSS_SET_FDO:
1020 {
1021 PDEVICE_OBJECT fdo;
1022 PUSB_DEV pdev;
1023
1024 if (irp_stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(PDEVICE_OBJECT))
1025 {
1026 EXIT_DISPATCH(STATUS_INVALID_PARAMETER, irp);
1027 }
1028
1029 fdo = (PDEVICE_OBJECT) ((PULONG) irp->AssociatedIrp.SystemBuffer)[0];
1030 if (fdo == NULL)
1031 EXIT_DISPATCH(STATUS_INVALID_PARAMETER, irp);
1032 //
1033 // we have to test the usb dev's state to determine whether set or not the fdo
1034 //
1035
1036 if (usb_query_and_lock_dev(pdev_ext->dev_mgr, pdev_ext->dev_handle, &pdev) !=
1037 STATUS_SUCCESS)
1038 EXIT_DISPATCH(STATUS_DEVICE_DOES_NOT_EXIST, irp);
1039
1040 lock_dev(pdev, FALSE);
1041
1042 if (dev_state(pdev) >= USB_DEV_STATE_BEFORE_ZOMB || dev_state(pdev) == USB_DEV_STATE_ZOMB)
1043 {
1044 unlock_dev(pdev, FALSE);
1045 usb_unlock_dev(pdev);
1046 EXIT_DISPATCH(STATUS_DEVICE_DOES_NOT_EXIST, irp);
1047 }
1048
1049 pdev_ext->fdo = fdo;
1050 unlock_dev(pdev, FALSE);
1051 usb_unlock_dev(pdev);
1052 irp->IoStatus.Information = 0;
1053 EXIT_DISPATCH(STATUS_SUCCESS, irp);
1054 }
1055
1056 case IOCTL_GET_DEV_DESC:
1057 {
1058 PGET_DEV_DESC_REQ pgddr;
1059 if (irp_stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(GET_DEV_DESC_REQ))
1060 {
1061 EXIT_DISPATCH(STATUS_INVALID_PARAMETER, irp);
1062 }
1063 pgddr = irp->AssociatedIrp.SystemBuffer;
1064 if (pgddr->dev_handle != (pdev_ext->dev_handle & 0xffff0000))
1065 {
1066 EXIT_DISPATCH(STATUS_INVALID_PARAMETER, irp);
1067 }
1068 // an immediate request
1069 return dev_mgr_dispatch(pdev_ext->dev_mgr, irp);
1070 }
1071 case IOCTL_SUBMIT_URB_RD:
1072 case IOCTL_SUBMIT_URB_NOIO:
1073 case IOCTL_SUBMIT_URB_WR:
1074 {
1075 PURB purb;
1076 DEV_HANDLE endp_handle;
1077
1078 if (irp_stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(URB))
1079 {
1080 EXIT_DISPATCH(STATUS_INVALID_PARAMETER, irp);
1081 }
1082
1083 purb = (PURB) irp->AssociatedIrp.SystemBuffer;
1084 endp_handle = purb->endp_handle;
1085 if (!default_endp_handle(endp_handle))
1086 {
1087 //no permit to other interface if interface dev
1088 if ((pdev_ext->flags & UMSS_DEV_FLAG_IF_DEV)
1089 && if_idx_from_handle(endp_handle) != pdev_ext->if_idx)
1090 EXIT_DISPATCH(STATUS_INVALID_PARAMETER, irp);
1091 }
1092 // FIXME: this is dangeous
1093 // return dev_mgr_dispatch( pdev_ext->dev_mgr, irp );
1094 UMSS_EXIT_DISPATCH(pdev_obj, STATUS_PENDING, irp);
1095 }
1096 case IOCTL_GET_DEV_HANDLE:
1097 {
1098 if (irp_stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(LONG))
1099 EXIT_DISPATCH(STATUS_INVALID_PARAMETER, irp);
1100
1101 *((PLONG) irp->AssociatedIrp.SystemBuffer) = pdev_ext->dev_handle;
1102 irp->IoStatus.Information = sizeof(LONG);
1103 EXIT_DISPATCH(STATUS_SUCCESS, irp);
1104 }
1105
1106 //
1107 // request from scsi class driver
1108 //
1109 case IOCTL_SCSI_PASS_THROUGH:
1110 case IOCTL_SCSI_PASS_THROUGH_DIRECT:
1111 //
1112 // direct cdb request
1113 //
1114 case IOCTL_UMSS_SUBMIT_CDB:
1115 case IOCTL_UMSS_SUBMIT_CDB_OUT:
1116 case IOCTL_UMSS_SUBMIT_CDB_IN:
1117 {
1118 UMSS_EXIT_DISPATCH(pdev_obj, STATUS_PENDING, irp);
1119 }
1120 case IOCTL_SCSI_GET_INQUIRY_DATA:
1121 {
1122 PSCSI_ADAPTER_BUS_INFO adapter_info;
1123 PSCSI_BUS_DATA bus_data;
1124 PSCSI_INQUIRY_DATA inq_dat;
1125 PINQUIRYDATA inq;
1126 IO_PACKET io_packet;
1127 ULONG required_size;
1128
1129 required_size = sizeof(SCSI_ADAPTER_BUS_INFO)
1130 + sizeof(SCSI_BUS_DATA) + sizeof(SCSI_INQUIRY_DATA) + INQUIRYDATABUFFERSIZE;
1131
1132 if (irp_stack->Parameters.DeviceIoControl.OutputBufferLength < required_size)
1133 UMSS_EXIT_DISPATCH(pdev_obj, STATUS_BUFFER_TOO_SMALL, irp);
1134
1135 RtlZeroMemory(&io_packet, sizeof(io_packet));
1136
1137 adapter_info = irp->AssociatedIrp.SystemBuffer;
1138 adapter_info->NumberOfBuses = 1;
1139 bus_data = &adapter_info->BusData[0];
1140 bus_data->NumberOfLogicalUnits = 1;
1141 bus_data->InitiatorBusId = 0;
1142 bus_data->InquiryDataOffset = sizeof(SCSI_ADAPTER_BUS_INFO);
1143 inq_dat = (PVOID) & bus_data[1];
1144 inq_dat->PathId = 0;
1145 inq_dat->TargetId = pdev_ext->umss_dev_id;
1146 //
1147 // this is the dev_id for usb dev_manager
1148 //
1149 inq_dat->Lun = (UCHAR) (pdev_ext->dev_handle >> 16);
1150 inq_dat->DeviceClaimed = FALSE;
1151 inq_dat->InquiryDataLength = 36;
1152 inq_dat->NextInquiryDataOffset = 0;
1153 inq = (PINQUIRYDATA) inq_dat->InquiryData;
1154
1155 RtlZeroMemory(inq, sizeof(INQUIRYDATA));
1156 inq->DeviceType = DIRECT_ACCESS_DEVICE;
1157 inq->DeviceTypeQualifier = 0;
1158 inq->RemovableMedia = 1;
1159
1160 //
1161 // pretend to comply scsi primary 2 command set
1162 //
1163
1164 inq->Versions = 0x04;
1165
1166 //
1167 // the format is in scsi-2 format
1168 //
1169
1170 inq->ResponseDataFormat = 0x02;
1171
1172 //
1173 // we are the poor scsi device
1174 //
1175
1176 inq->AdditionalLength = 31;
1177 inq->SoftReset = 0;
1178 inq->CommandQueue = 0;
1179 inq->LinkedCommands = 0;
1180 inq->RelativeAddressing = 0;
1181 RtlCopyMemory(&inq->VendorId, "Unknown", 7);
1182 RtlCopyMemory(&inq->ProductId, "USB Mass Storage", 16);
1183 irp->IoStatus.Information = required_size;
1184 EXIT_DISPATCH(STATUS_SUCCESS, irp);
1185 }
1186 case IOCTL_SCSI_GET_CAPABILITIES:
1187 {
1188 PIO_SCSI_CAPABILITIES port_cap;
1189
1190 if (irp_stack->Parameters.DeviceIoControl.OutputBufferLength <
1191 sizeof(IO_SCSI_CAPABILITIES))
1192 EXIT_DISPATCH(STATUS_INVALID_PARAMETER, irp);
1193
1194 port_cap = (PIO_SCSI_CAPABILITIES) irp->AssociatedIrp.SystemBuffer;
1195 port_cap->Length = sizeof(IO_SCSI_CAPABILITIES);
1196 port_cap->MaximumTransferLength = 65536;
1197 port_cap->MaximumPhysicalPages = 65536 / PAGE_SIZE;
1198 port_cap->SupportedAsynchronousEvents = 0;
1199 port_cap->AlignmentMask = 0x10;
1200 port_cap->TaggedQueuing = FALSE;
1201 port_cap->AdapterScansDown = FALSE;
1202 port_cap->AdapterUsesPio = FALSE;
1203 irp->IoStatus.Information = sizeof(IO_SCSI_CAPABILITIES);
1204 EXIT_DISPATCH(STATUS_SUCCESS, irp);
1205 }
1206 case IOCTL_SCSI_GET_ADDRESS:
1207 {
1208 PSCSI_ADDRESS paddr;
1209 if (irp_stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(SCSI_ADDRESS))
1210 EXIT_DISPATCH(STATUS_INVALID_PARAMETER, irp);
1211
1212 paddr = (PSCSI_ADDRESS) irp->AssociatedIrp.SystemBuffer;
1213
1214 paddr->Length = sizeof(SCSI_ADDRESS);
1215 paddr->PortNumber = 0;
1216 paddr->PathId = 0;
1217 paddr->TargetId = pdev_ext->umss_dev_id;
1218 paddr->Lun = (UCHAR) (pdev_ext->dev_handle >> 16);
1219 irp->IoStatus.Information = sizeof(SCSI_ADDRESS);
1220 EXIT_DISPATCH(STATUS_SUCCESS, irp);
1221 }
1222 case IOCTL_SCSI_RESCAN_BUS:
1223 {
1224 irp->IoStatus.Information = 0;
1225 EXIT_DISPATCH(STATUS_SUCCESS, irp);
1226 }
1227 default:
1228 {
1229 EXIT_DISPATCH(STATUS_INVALID_DEVICE_REQUEST, irp);
1230 }
1231 }
1232 }
1233 }
1234 EXIT_DISPATCH(STATUS_NOT_SUPPORTED, irp);
1235 }
1236
1237 VOID
1238 umss_reset_pipe_completion(PURB purb, PVOID context)
1239 {
1240 PUMSS_DEVICE_EXTENSION pdev_ext;
1241 if (context == NULL)
1242 return;
1243
1244 pdev_ext = (PUMSS_DEVICE_EXTENSION) context;
1245 pdev_ext->reset_pipe_status = purb->status;
1246 KeSetEvent(&pdev_ext->sync_event, 0, FALSE);
1247 return;
1248 }
1249
1250 //can only be called at passive level
1251 NTSTATUS
1252 umss_reset_pipe(PUMSS_DEVICE_EXTENSION pdev_ext, DEV_HANDLE endp_handle)
1253 {
1254 NTSTATUS status;
1255 PUSB_DEV pdev;
1256
1257 if (pdev_ext == NULL)
1258 return STATUS_INVALID_PARAMETER;
1259
1260 status = usb_query_and_lock_dev(pdev_ext->dev_mgr, pdev_ext->dev_handle, &pdev);
1261
1262 if (status != STATUS_SUCCESS)
1263 return STATUS_UNSUCCESSFUL;
1264
1265 status = usb_reset_pipe_ex(pdev_ext->dev_mgr, endp_handle, umss_reset_pipe_completion, pdev_ext);
1266
1267 if (status == STATUS_PENDING)
1268 {
1269 KeWaitForSingleObject(&pdev_ext->sync_event, Executive, KernelMode, TRUE, NULL);
1270 status = pdev_ext->reset_pipe_status;
1271 }
1272 usb_unlock_dev(pdev);
1273 return status;
1274 }
1275
1276 BOOLEAN
1277 umss_gen_result_srb(PIO_PACKET io_packet, PSCSI_REQUEST_BLOCK srb, NTSTATUS status)
1278 {
1279
1280 if (srb == NULL || io_packet == NULL)
1281 {
1282 return FALSE;
1283 }
1284 if (status == STATUS_SUCCESS)
1285 {
1286 PULONG dest_buf, src_buf;
1287 ULONG i;
1288
1289 srb->SrbStatus = SRB_STATUS_SUCCESS;
1290
1291 io_packet->pirp->IoStatus.Information = srb->DataTransferLength;
1292 if ((io_packet->pirp->Flags & IRP_READ_OPERATION) && !(io_packet->pirp->Flags & IRP_PAGING_IO))
1293 {
1294 src_buf = (PULONG) io_packet->data_buffer;
1295 dest_buf = (PULONG) srb->DataBuffer;
1296 if (src_buf && dest_buf)
1297 {
1298 for(i = 0; i < (srb->DataTransferLength >> 2); i++)
1299 {
1300 dest_buf[i] = src_buf[i];
1301 }
1302 }
1303 }
1304 }
1305 else if (status == STATUS_DEVICE_DOES_NOT_EXIST)
1306 {
1307 PSENSE_DATA sense_buf;
1308 srb->SrbStatus = SRB_STATUS_NO_DEVICE;
1309 srb->ScsiStatus = SCSISTAT_CHECK_CONDITION;
1310
1311 //
1312 // let's build the srb status for class driver
1313 //
1314
1315 srb->SrbStatus |= SRB_STATUS_AUTOSENSE_VALID;
1316 sense_buf = (PSENSE_DATA) srb->SenseInfoBuffer;
1317
1318 if (!(srb->SrbFlags & SRB_FLAGS_DISABLE_AUTOSENSE))
1319 {
1320 RtlZeroMemory(srb->SenseInfoBuffer, srb->SenseInfoBufferLength);
1321 sense_buf->ErrorCode = 0x70;
1322 sense_buf->Valid = 1;
1323 sense_buf->SenseKey = SCSI_SENSE_NOT_READY;
1324 sense_buf->AdditionalSenseCode = SCSI_ADSENSE_NO_MEDIA_IN_DEVICE;
1325 sense_buf->AdditionalSenseLength = 10;
1326 }
1327 }
1328 else if (status == USB_STATUS_STALL_PID || status == USB_STATUS_CRC ||
1329 status == USB_STATUS_BTSTUFF || status == USB_STATUS_DATA_OVERRUN)
1330 {
1331 PSENSE_DATA sense_buf;
1332 srb->SrbStatus = SRB_STATUS_ERROR;
1333 srb->ScsiStatus = SCSISTAT_CHECK_CONDITION;
1334
1335 srb->SrbStatus |= SRB_STATUS_AUTOSENSE_VALID;
1336 sense_buf = (PSENSE_DATA) srb->SenseInfoBuffer;
1337
1338 if (!(srb->SrbFlags & SRB_FLAGS_DISABLE_AUTOSENSE))
1339 {
1340 RtlZeroMemory(srb->SenseInfoBuffer, srb->SenseInfoBufferLength);
1341 sense_buf->ErrorCode = 0x70;
1342 sense_buf->Valid = 1;
1343 sense_buf->SenseKey = SCSI_SENSE_HARDWARE_ERROR;
1344 sense_buf->AdditionalSenseCode = 0;
1345 sense_buf->AdditionalSenseLength = 10;
1346 }
1347 }
1348 else
1349 {
1350 srb->SrbStatus = SRB_STATUS_ERROR;
1351 }
1352
1353 if ((io_packet->pirp->Flags & (IRP_READ_OPERATION | IRP_WRITE_OPERATION))
1354 && !(io_packet->pirp->Flags & IRP_PAGING_IO))
1355 {
1356 if (io_packet->data_buffer)
1357 {
1358 usb_free_mem(io_packet->data_buffer);
1359 io_packet->data_buffer = NULL;
1360 }
1361 }
1362 return TRUE;
1363 }
1364
1365 BOOLEAN
1366 umss_gen_result_ctrl(PDEVICE_OBJECT dev_obj, PIRP irp, NTSTATUS status)
1367 {
1368 PIO_STACK_LOCATION irp_stack;
1369 ULONG ctrl_code;
1370 PUMSS_DEVICE_EXTENSION pdev_ext;
1371
1372 if (irp == NULL)
1373 return FALSE;
1374
1375 irp->IoStatus.Information = 0;
1376 irp_stack = IoGetCurrentIrpStackLocation(irp);
1377 ctrl_code = irp_stack->Parameters.DeviceIoControl.IoControlCode;
1378 pdev_ext = dev_obj->DeviceExtension;
1379
1380 switch (ctrl_code)
1381 {
1382 case IOCTL_SCSI_PASS_THROUGH:
1383 {
1384 PSCSI_PASS_THROUGH pass_through;
1385 pass_through = irp->AssociatedIrp.SystemBuffer;
1386 irp->IoStatus.Status = status;
1387
1388 // we have set these two value in bulkonly.c when data transfer complete
1389 // pass_through_direct->DataTransferLength = pdev_ext->io_packet.data_length;
1390 // pass_through_direct->SenseInfoLength = pdev_ext->io_packet.sense_data_length;
1391
1392 if (status == STATUS_SUCCESS)
1393 irp->IoStatus.Information = pass_through->SenseInfoOffset + pass_through->SenseInfoLength;
1394 else
1395 pass_through->ScsiStatus = SCSISTAT_CHECK_CONDITION;
1396 return TRUE;
1397 }
1398 case IOCTL_SCSI_PASS_THROUGH_DIRECT:
1399 {
1400 PSCSI_PASS_THROUGH_DIRECT pass_through_direct;
1401
1402 pass_through_direct = irp->AssociatedIrp.SystemBuffer;
1403 pass_through_direct->ScsiStatus = 0;
1404 irp->IoStatus.Status = status;
1405
1406 // we have set these two value in bulkonly.c when data transfer complete
1407 // pass_through_direct->DataTransferLength = pdev_ext->io_packet.data_length;
1408 // pass_through_direct->SenseInfoLength = pdev_ext->io_packet.sense_data_length;
1409
1410 if (status == STATUS_SUCCESS)
1411 irp->IoStatus.Information =
1412 pass_through_direct->SenseInfoOffset + pass_through_direct->SenseInfoLength;
1413 else
1414 pass_through_direct->ScsiStatus = SCSISTAT_CHECK_CONDITION;
1415
1416 return TRUE;
1417 }
1418 }
1419 return FALSE;
1420 }
1421
1422
1423 VOID
1424 umss_complete_request(PUMSS_DEVICE_EXTENSION pdev_ext, NTSTATUS status)
1425 {
1426 PIRP pirp;
1427 KIRQL old_irql;
1428
1429 PDEVICE_OBJECT dev_obj;
1430 PIO_STACK_LOCATION irp_stack;
1431
1432 usb_dbg_print(DBGLVL_MAXIMUM, ("umss_complete_request(): entering...\n"));
1433
1434 pirp = pdev_ext->io_packet.pirp;
1435 dev_obj = pdev_ext->pdo;
1436
1437 irp_stack = IoGetCurrentIrpStackLocation(pirp);
1438
1439 if (pdev_ext->io_packet.flags & IOP_FLAG_SRB_TRANSFER)
1440 {
1441 if (pdev_ext->pif_desc->bInterfaceSubClass == UMSS_SUBCLASS_SFF8070I)
1442 {
1443 umss_fix_sff_result(&pdev_ext->io_packet, irp_stack->Parameters.Scsi.Srb);
1444 }
1445 umss_gen_result_srb(&pdev_ext->io_packet, irp_stack->Parameters.Scsi.Srb, status);
1446 }
1447 else if (pdev_ext->io_packet.flags & IOP_FLAG_SCSI_CTRL_TRANSFER)
1448 umss_gen_result_ctrl(dev_obj, pirp, status);
1449
1450 //this device has its irp queued
1451 if (status == STATUS_CANCELLED)
1452 {
1453 usb_dbg_print(DBGLVL_MAXIMUM, ("umss_complete_request(): status of irp is cancelled\n"));
1454 IoAcquireCancelSpinLock(&old_irql);
1455 if (dev_obj->CurrentIrp == pirp)
1456 {
1457 IoReleaseCancelSpinLock(old_irql);
1458 IoStartNextPacket(dev_obj, FALSE);
1459 }
1460 else
1461 {
1462 KeRemoveEntryDeviceQueue(&dev_obj->DeviceQueue, &pirp->Tail.Overlay.DeviceQueueEntry);
1463 IoReleaseCancelSpinLock(old_irql);
1464 }
1465 }
1466 else
1467 {
1468 // all requests come to this point from the irp queue
1469 IoStartNextPacket(dev_obj, FALSE);
1470
1471 // we are going to complete the request, so set it's cancel routine to NULL
1472 IoAcquireCancelSpinLock(&old_irql);
1473 (void)IoSetCancelRoutine(pirp, NULL);
1474 IoReleaseCancelSpinLock(old_irql);
1475 }
1476
1477 pirp->IoStatus.Status = status;
1478
1479 if (status != STATUS_SUCCESS)
1480 pirp->IoStatus.Information = 0;
1481
1482 IoCompleteRequest(pirp, IO_NO_INCREMENT);
1483 return;
1484 }
1485
1486 BOOLEAN
1487 umss_if_connect(PDEV_CONNECT_DATA params, DEV_HANDLE if_handle)
1488 {
1489 PURB purb;
1490 LONG if_idx, i;
1491 PUCHAR desc_buf;
1492 NTSTATUS status;
1493 PUSB_DEV pdev;
1494 PUSB_DRIVER pdrvr;
1495 PUSB_INTERFACE_DESC pif_desc;
1496 PUSB_CTRL_SETUP_PACKET psetup;
1497 PUMSS_DEVICE_EXTENSION pdev_ext;
1498 PUSB_CONFIGURATION_DESC pconfig_desc;
1499 PUSB_DEV_MANAGER dev_mgr;
1500 PUSB_ENDPOINT_DESC pendp_desc;
1501 PUMSS_DRVR_EXTENSION pdrvr_ext;
1502 PDEVICE_OBJECT pdev_obj;
1503 USE_BASIC_NON_PENDING_IRQL;
1504
1505 //configuration is already set
1506 purb = NULL;
1507 desc_buf = NULL;
1508 pdev = NULL;
1509
1510 usb_dbg_print(DBGLVL_MAXIMUM, ("umss_if_connect(): entering...\n"));
1511
1512 if (params == NULL)
1513 return FALSE;
1514
1515 dev_mgr = params->dev_mgr;
1516 pdrvr = params->pdriver;
1517
1518 if_idx = if_idx_from_handle(if_handle);
1519
1520 purb = usb_alloc_mem(NonPagedPool, sizeof(URB));
1521 if (purb == NULL)
1522 goto ERROR_OUT;
1523
1524 desc_buf = usb_alloc_mem(NonPagedPool, 512);
1525 if (desc_buf == NULL)
1526 goto ERROR_OUT;
1527
1528 psetup = (PUSB_CTRL_SETUP_PACKET) (purb)->setup_packet;
1529 urb_init((purb));
1530
1531 // now let's get the descs, one configuration, one interface and two endpoint
1532 psetup = (PUSB_CTRL_SETUP_PACKET) (purb)->setup_packet;
1533 purb->endp_handle = if_handle | 0xffff;
1534 purb->data_buffer = desc_buf;
1535 purb->data_length = 512;
1536 purb->completion = NULL; // this is an immediate request, no needs completion
1537 purb->context = dev_mgr;
1538 purb->reference = 0;
1539 psetup->bmRequestType = 0x80;
1540 psetup->bRequest = USB_REQ_GET_DESCRIPTOR;
1541 psetup->wValue = USB_DT_CONFIG << 8;
1542 psetup->wIndex = 0;
1543 psetup->wLength = 512;
1544
1545 status = usb_submit_urb(dev_mgr, purb);
1546 if (status == STATUS_PENDING)
1547 {
1548 TRAP();
1549 }
1550 usb_free_mem(purb);
1551 purb = NULL;
1552
1553 if (status != STATUS_SUCCESS)
1554 {
1555 goto ERROR_OUT;
1556 }
1557
1558 status = usb_query_and_lock_dev(dev_mgr, if_handle, &pdev);
1559 if (status != STATUS_SUCCESS)
1560 {
1561 goto ERROR_OUT;
1562 }
1563
1564 #ifdef _TIANSHENG_DRIVER
1565 if (!((pdev->pusb_dev_desc->idVendor == 0x03eb && pdev->pusb_dev_desc->idProduct == 0x2002)
1566 || (pdev->pusb_dev_desc->idVendor == 0x0ea0 && pdev->pusb_dev_desc->idProduct == 0x6803)
1567 || (pdev->pusb_dev_desc->idVendor == 0x0ef5 && pdev->pusb_dev_desc->idProduct == 0x2202)))
1568 {
1569 // check TianSheng's product
1570 goto ERROR_OUT;
1571 }
1572 #endif
1573
1574 pdev_obj = umss_create_device(dev_mgr, pdrvr, if_handle, TRUE);
1575 if (pdev_obj == NULL)
1576 {
1577 goto ERROR_OUT;
1578 }
1579
1580 lock_dev(pdev, FALSE);
1581 if (dev_state(pdev) == USB_DEV_STATE_ZOMB ||
1582 dev_mgr_set_if_driver(dev_mgr, if_handle, pdrvr, pdev) == FALSE)
1583 {
1584 unlock_dev(pdev, FALSE);
1585 if (pdev_obj)
1586 {
1587 umss_delete_device(dev_mgr, pdrvr, pdev_obj, TRUE);
1588 }
1589 goto ERROR_OUT;
1590 }
1591
1592 if (pdev->usb_config)
1593 {
1594 pdev->usb_config->interf[if_idx].if_ext = pdev_obj;
1595 pdev->usb_config->interf[if_idx].if_ext_size = 0;
1596 }
1597 // olympus dev needs special care
1598 if (UMSS_OLYMPUS_VENDOR_ID == pdev->pusb_dev_desc->idVendor)
1599 status = TRUE;
1600 else
1601 status = FALSE;
1602
1603 unlock_dev(pdev, FALSE);
1604
1605 pdev_ext = (PUMSS_DEVICE_EXTENSION) pdev_obj->DeviceExtension;
1606
1607 pdev_ext->desc_buf = desc_buf;
1608 pdev_ext->pif_desc = NULL;
1609 pdev_ext->pin_endp_desc = pdev_ext->pout_endp_desc = NULL;
1610 pconfig_desc = (PUSB_CONFIGURATION_DESC) desc_buf;
1611 pif_desc = (PUSB_INTERFACE_DESC) (&pconfig_desc[1]);
1612
1613 if (status)
1614 pdev_ext->flags |= UMSS_DEV_FLAG_OLYMPUS_DEV;
1615
1616 //search for our if
1617 for(i = 0; ((UCHAR) i) < if_idx; i++)
1618 {
1619 if (usb_skip_if_and_altif((PUCHAR *) & pif_desc) == FALSE)
1620 break;
1621 }
1622 pdev_ext->pif_desc = pif_desc;
1623
1624 if (pdev_ext->pif_desc)
1625 {
1626 pendp_desc = (PUSB_ENDPOINT_DESC) & pif_desc[1];
1627 for(i = 0; ((UCHAR) i) < pif_desc->bNumEndpoints; i++)
1628 {
1629 if (pendp_desc->bDescriptorType == USB_DT_ENDPOINT
1630 && pendp_desc->bLength == sizeof(USB_ENDPOINT_DESC))
1631 {
1632 if ((pendp_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)
1633 {
1634 pdev_ext->pint_endp_desc = pendp_desc;
1635 pdev_ext->int_endp_idx = (UCHAR) i;
1636 }
1637 else if ((pendp_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK)
1638 {
1639 if (pendp_desc->bEndpointAddress & USB_DIR_IN)
1640 {
1641 pdev_ext->pin_endp_desc = pendp_desc;
1642 pdev_ext->in_endp_idx = (UCHAR) i;
1643 }
1644 else
1645 {
1646 pdev_ext->pout_endp_desc = pendp_desc;
1647 pdev_ext->out_endp_idx = (UCHAR) i;
1648 }
1649 }
1650 pendp_desc = &pendp_desc[1];
1651 }
1652 else
1653 break;
1654 }
1655 }
1656
1657 // notify the class driver, some device comes
1658 pdrvr_ext = (PUMSS_DRVR_EXTENSION) pdrvr->driver_ext;
1659 if (pdrvr_ext && pdrvr_ext->class_driver_info.add_device && pdrvr_ext->class_driver_info.fdo_driver)
1660 pdrvr_ext->class_driver_info.add_device(pdrvr_ext->class_driver_info.fdo_driver, pdev_obj);
1661
1662 usb_unlock_dev(pdev);
1663 return TRUE;
1664
1665 ERROR_OUT:
1666 if (desc_buf)
1667 usb_free_mem(desc_buf);
1668
1669 if (purb)
1670 usb_free_mem(purb);
1671
1672 usb_unlock_dev(pdev);
1673
1674 desc_buf = NULL;
1675 purb = NULL;
1676
1677 return FALSE;
1678 }
1679
1680 BOOLEAN
1681 umss_if_disconnect(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE if_handle)
1682 {
1683 LONG if_idx;
1684 NTSTATUS status;
1685 PUSB_DEV pdev;
1686 PUSB_DRIVER pdrvr = NULL;
1687 PDEVICE_OBJECT dev_obj = NULL;
1688 PUMSS_DRVR_EXTENSION pdrvr_ext;
1689 PUMSS_DEVICE_EXTENSION pdev_ext;
1690
1691 if (dev_mgr == NULL || if_handle == 0)
1692 return FALSE;
1693
1694 pdev = NULL;
1695 if_idx = if_idx_from_handle(if_handle);
1696 //
1697 // special use of the lock dev, simply use this routine to get the dev
1698 //
1699 status = usb_query_and_lock_dev(dev_mgr, if_handle, &pdev);
1700 if (pdev == NULL)
1701 {
1702 return FALSE;
1703 }
1704 if (status == STATUS_SUCCESS)
1705 {
1706 // must be a bug
1707 TRAP();
1708 }
1709 if (pdev->usb_config)
1710 {
1711 pdrvr = pdev->usb_config->interf[if_idx].pif_drv;
1712 dev_obj = (PDEVICE_OBJECT) pdev->usb_config->interf[if_idx].if_ext;
1713 }
1714 pdev = NULL;
1715
1716 // notify the class driver, some device gone
1717 pdrvr_ext = (PUMSS_DRVR_EXTENSION) pdrvr->driver_ext;
1718 pdev_ext = dev_obj->DeviceExtension;
1719 if (pdrvr_ext && pdrvr_ext->class_driver_info.pnp_dispatch)
1720 pdrvr_ext->class_driver_info.pnp_dispatch(dev_obj, UMSS_PNPMSG_DISCONNECT, NULL);
1721
1722 // no need to unlock the dev
1723 return umss_delete_device(dev_mgr, pdrvr, dev_obj, TRUE);
1724 }
1725
1726 BOOLEAN
1727 umss_if_stop(PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE if_handle)
1728 {
1729 LONG if_idx;
1730 NTSTATUS status;
1731 PUSB_DEV pdev;
1732 PUSB_DRIVER pdrvr = NULL;
1733 PDEVICE_OBJECT dev_obj = NULL;
1734 PUMSS_DRVR_EXTENSION pdrvr_ext;
1735 PUMSS_DEVICE_EXTENSION pdev_ext;
1736 USE_BASIC_NON_PENDING_IRQL;
1737
1738 if (dev_mgr == NULL || if_handle == 0)
1739 return FALSE;
1740
1741 pdev = NULL;
1742 if_idx = if_idx_from_handle(if_handle);
1743
1744 // special use of the lock dev, simply use this routine to get the dev
1745 status = usb_query_and_lock_dev(dev_mgr, if_handle, &pdev);
1746 if (status != STATUS_SUCCESS)
1747 {
1748 return FALSE;
1749 }
1750
1751 lock_dev(pdev, FALSE);
1752 if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
1753 {
1754 return FALSE;
1755 }
1756
1757 if (pdev->usb_config)
1758 {
1759 pdrvr = pdev->usb_config->interf[if_idx].pif_drv;
1760 dev_obj = (PDEVICE_OBJECT) pdev->usb_config->interf[if_idx].if_ext;
1761 }
1762 unlock_dev(pdev, FALSE);
1763
1764 // notify the class driver, some device stops
1765 pdev_ext = dev_obj->DeviceExtension;
1766 pdrvr_ext = (PUMSS_DRVR_EXTENSION) pdrvr->driver_ext;
1767 if (pdrvr_ext && pdrvr_ext->class_driver_info.pnp_dispatch)
1768 pdrvr_ext->class_driver_info.pnp_dispatch(dev_obj, UMSS_PNPMSG_STOP, NULL);
1769
1770 usb_unlock_dev(pdev);
1771 return TRUE;
1772 }
1773
1774 VOID
1775 umss_load_class_driver(PVOID context)
1776 {
1777 NTSTATUS status;
1778 UNICODE_STRING unicode_string;
1779
1780 UNREFERENCED_PARAMETER(context);
1781
1782 //
1783 // let's load the class driver
1784 //
1785 RtlInitUnicodeString(&unicode_string,
1786 L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\usbstor");
1787 status = ZwLoadDriver(&unicode_string);
1788 usb_dbg_print(DBGLVL_MAXIMUM,
1789 ("umss_load_class_driver(): try to load class driver, status=0x%x\n", status));
1790 }
1791
1792 BOOLEAN
1793 umss_if_driver_init(PUSB_DEV_MANAGER dev_mgr, PUSB_DRIVER pdriver)
1794 {
1795 PUMSS_DRVR_EXTENSION pdrvr_ext;
1796
1797 if (dev_mgr == NULL || pdriver == NULL)
1798 return FALSE;
1799
1800 //init driver structure, no PNP table functions
1801
1802 pdriver->driver_desc.flags = USB_DRIVER_FLAG_IF_CAPABLE;
1803 pdriver->driver_desc.vendor_id = 0x0000; // USB Vendor ID
1804 pdriver->driver_desc.product_id = 0x0000; // USB Product ID.
1805 pdriver->driver_desc.release_num = 0x100; // Release Number of Device
1806
1807 pdriver->driver_desc.config_val = 1; // Configuration Value
1808 pdriver->driver_desc.if_num = 1; // Interface Number
1809 pdriver->driver_desc.if_class = USB_CLASS_MASS_STORAGE; // Interface Class
1810 pdriver->driver_desc.if_sub_class = 0; // Interface SubClass
1811 pdriver->driver_desc.if_protocol = 0; // Interface Protocol
1812
1813 pdriver->driver_desc.driver_name = "USB Mass Storage interface driver"; // Driver name for Name Registry
1814 pdriver->driver_desc.dev_class = USB_CLASS_PER_INTERFACE;
1815 pdriver->driver_desc.dev_sub_class = 0; // Device Subclass
1816 pdriver->driver_desc.dev_protocol = 0; // Protocol Info.
1817
1818 pdriver->driver_ext = usb_alloc_mem(NonPagedPool, sizeof(UMSS_DRVR_EXTENSION));
1819 if (!pdriver->driver_ext) return FALSE;
1820
1821 pdriver->driver_ext_size = sizeof(UMSS_DRVR_EXTENSION);
1822
1823 RtlZeroMemory(pdriver->driver_ext, sizeof(UMSS_DRVR_EXTENSION));
1824
1825 pdrvr_ext = (PUMSS_DRVR_EXTENSION) pdriver->driver_ext;
1826 pdrvr_ext->dev_count = 0;
1827 InitializeListHead(&pdrvr_ext->dev_list);
1828 ExInitializeFastMutex(&pdrvr_ext->dev_list_mutex);
1829
1830 pdriver->disp_tbl.version = 1;
1831 pdriver->disp_tbl.dev_connect = umss_if_connect;
1832 pdriver->disp_tbl.dev_disconnect = umss_if_disconnect;
1833 pdriver->disp_tbl.dev_stop = umss_if_stop;
1834 pdriver->disp_tbl.dev_reserved = NULL;
1835
1836 if ((pdrvr_ext->port_dev_obj = umss_create_port_device(dev_mgr, pdriver)) == NULL)
1837 {
1838 usb_free_mem(pdriver->driver_ext);
1839 pdriver->driver_ext = NULL;
1840 pdriver->driver_ext_size = 0;
1841 pdriver->disp_tbl.dev_connect = NULL;
1842 pdriver->disp_tbl.dev_stop = NULL;
1843 pdriver->disp_tbl.dev_disconnect = NULL;
1844 return FALSE;
1845 }
1846
1847 //
1848 // let's load the class driver
1849 //
1850 umss_load_class_driver(NULL);
1851
1852 // umss_schedule_workitem( NULL, umss_load_class_driver, NULL, 0 );
1853 usb_dbg_print(DBGLVL_MAXIMUM, ("umss_if_driver_init(): umss driver is initialized\n"));
1854
1855 return TRUE;
1856 }
1857
1858 // get the driver reg information for pnp notification to class
1859 // driver.
1860 // bug??? how if the driver info is returned while the driver
1861 // is being unloaded.
1862 // So the routine must be called when usb_query_and_lock_dev is
1863 // called.
1864 PCLASS_DRV_REG_INFO
1865 umss_get_if_driver_info(PUSB_DEV_MANAGER dev_mgr, PUSB_DEV pdev, DEV_HANDLE if_handle)
1866 {
1867 PUMSS_DRVR_EXTENSION drvr_ext;
1868 ULONG if_idx;
1869 USE_BASIC_NON_PENDING_IRQL;
1870
1871 UNREFERENCED_PARAMETER(dev_mgr);
1872
1873 if_idx = if_idx_from_handle(if_handle);
1874 if (if_idx >= 4) // max interfaces per config supports. defined in td.h
1875 return NULL;
1876
1877 ASSERT(pdev != NULL);
1878
1879 lock_dev(pdev, FALSE);
1880 if (dev_state(pdev) == USB_DEV_STATE_ZOMB)
1881 {
1882 unlock_dev(pdev, FALSE);
1883 usb_unlock_dev(pdev);
1884 return NULL;
1885 }
1886
1887 drvr_ext = NULL;
1888
1889 if (pdev->usb_config->interf[if_idx].pif_drv)
1890 drvr_ext = (PUMSS_DRVR_EXTENSION) pdev->usb_config->interf[if_idx].pif_drv->driver_ext;
1891 else
1892 TRAP();
1893
1894 unlock_dev(pdev, FALSE);
1895
1896 if (drvr_ext == NULL)
1897 {
1898 return NULL;
1899 }
1900
1901 return &drvr_ext->class_driver_info;
1902 }
1903
1904 VOID NTAPI
1905 umss_worker(IN PVOID reference)
1906 {
1907 PUMSS_WORKER_PACKET worker_packet;
1908 PUSB_DEV pdev;
1909
1910 usb_dbg_print(DBGLVL_MAXIMUM, ("umss_worker(): entering...\n"));
1911 worker_packet = (PUMSS_WORKER_PACKET) reference;
1912 worker_packet->completion(worker_packet->context);
1913 if (worker_packet->dev_mgr && worker_packet->pdev)
1914 {
1915 pdev = (PUSB_DEV) worker_packet->pdev;
1916 usb_unlock_dev(pdev);
1917 pdev = NULL;
1918 }
1919 usb_free_mem(worker_packet);
1920 usb_dbg_print(DBGLVL_MAXIMUM, ("umss_worker(): exit\n"));
1921 }
1922
1923 /*++
1924 Routine Description:
1925
1926 Wrapper for handling worker thread callbacks, it is importent to
1927 lock the dev from being deleted by calling usb_query_and_lock_dev
1928 and in umss_worker, call the usb_unlock_dev to release the ref
1929 count. One exception is that the umss_if_disconnect call this
1930 function to delete the device object that is still held by some
1931 others, and deferred deletion is required.
1932
1933 Arguments:
1934
1935 Routine - Routine to be called when this work-item is processed
1936 Context - Value to be passed to worker routine
1937
1938 Return Value:
1939 TRUE if work item queued
1940 FALSE if work item not queued
1941
1942 --*/
1943 BOOLEAN
1944 umss_schedule_workitem(PVOID context,
1945 UMSS_WORKER_ROUTINE completion, PUSB_DEV_MANAGER dev_mgr, DEV_HANDLE dev_handle)
1946 {
1947 BOOLEAN ret_val = TRUE;
1948 PWORK_QUEUE_ITEM workitem;
1949 PUMSS_WORKER_PACKET worker_packet;
1950
1951 worker_packet = usb_alloc_mem(NonPagedPool, sizeof(WORK_QUEUE_ITEM) + sizeof(UMSS_WORKER_PACKET));
1952
1953 if (worker_packet)
1954 {
1955 RtlZeroMemory(worker_packet, sizeof(WORK_QUEUE_ITEM) + sizeof(UMSS_WORKER_PACKET));
1956
1957 workitem = (PWORK_QUEUE_ITEM) & worker_packet[1];
1958 worker_packet->completion = completion;
1959 worker_packet->context = context;
1960
1961 if (dev_mgr != NULL && dev_handle != 0)
1962 {
1963 PUSB_DEV pdev;
1964 // lock the device until the workitem is executed.
1965 if (usb_query_and_lock_dev(dev_mgr, dev_handle, &pdev) == STATUS_SUCCESS)
1966 {
1967 worker_packet->dev_mgr = dev_mgr;
1968 worker_packet->pdev = pdev;
1969 }
1970 else
1971 {
1972 usb_free_mem(worker_packet);
1973 return FALSE;
1974 }
1975 }
1976 // Initialize the work-item
1977 ExInitializeWorkItem(workitem, umss_worker, worker_packet);
1978
1979 // Schedule the work-item
1980 ExQueueWorkItem(workitem, DelayedWorkQueue);
1981
1982 usb_dbg_print(DBGLVL_MINIMUM, ("umss_schedule_workitem(): work-item queued\n"));
1983 }
1984 else
1985 {
1986 usb_dbg_print(DBGLVL_MINIMUM, ("umss_schedule_workitem(): Failed to allocate work-item\n"));
1987 ret_val = FALSE;
1988 }
1989
1990 return ret_val;
1991 }
1992
1993 NTSTATUS
1994 umss_process_srb(PDEVICE_OBJECT dev_obj, PIRP irp)
1995 {
1996 NTSTATUS status;
1997 PUSB_DEV pdev;
1998 PIO_STACK_LOCATION cur_stack;
1999 PUMSS_DEVICE_EXTENSION pdev_ext;
2000 PSCSI_REQUEST_BLOCK srb;
2001
2002 if (dev_obj == NULL || irp == NULL)
2003 return STATUS_INVALID_PARAMETER;
2004
2005 pdev = NULL;
2006 cur_stack = IoGetCurrentIrpStackLocation(irp);
2007 srb = cur_stack->Parameters.Scsi.Srb;
2008
2009 if (srb == NULL || srb->DataTransferLength > 65536)
2010 {
2011 status = STATUS_INVALID_PARAMETER;
2012 goto ERROR_OUT;
2013 }
2014
2015 irp->IoStatus.Status = STATUS_SUCCESS;
2016 irp->IoStatus.Information = 0;
2017
2018 pdev_ext = (PUMSS_DEVICE_EXTENSION) dev_obj->DeviceExtension;
2019 if ((status = usb_query_and_lock_dev(pdev_ext->dev_mgr, pdev_ext->dev_handle, &pdev)) != STATUS_SUCCESS)
2020 {
2021 PSENSE_DATA sense_buf;
2022 srb->SrbStatus = SRB_STATUS_NO_DEVICE;
2023
2024 //
2025 // let's build the srb status for class driver
2026 //
2027 srb->SrbStatus |= SRB_STATUS_AUTOSENSE_VALID;
2028 RtlZeroMemory(srb->SenseInfoBuffer, srb->SenseInfoBufferLength);
2029 if (!(srb->SrbFlags & SRB_FLAGS_DISABLE_AUTOSENSE))
2030 {
2031 sense_buf = (PSENSE_DATA) srb->SenseInfoBuffer;
2032 sense_buf->ErrorCode = 0x70;
2033 sense_buf->Valid = 1;
2034 sense_buf->SenseKey = SCSI_SENSE_NOT_READY;
2035 sense_buf->AdditionalSenseCode = SCSI_ADSENSE_NO_MEDIA_IN_DEVICE;
2036 sense_buf->AdditionalSenseLength = 10;
2037 }
2038 goto ERROR_OUT;
2039 }
2040
2041 switch (srb->Function)
2042 {
2043 case SRB_FUNCTION_EXECUTE_SCSI:
2044 {
2045 IO_PACKET io_packet;
2046 RtlZeroMemory(&io_packet, sizeof(io_packet));
2047
2048 io_packet.flags |= IOP_FLAG_SRB_TRANSFER;
2049 if (srb->SrbFlags & SRB_FLAGS_DATA_IN)
2050 io_packet.flags |= IOP_FLAG_DIR_IN;
2051 if (!(srb->SrbFlags & SRB_FLAGS_DISABLE_AUTOSENSE))
2052 io_packet.flags |= IOP_FLAG_REQ_SENSE;
2053
2054 io_packet.cdb_length = srb->CdbLength;
2055 RtlCopyMemory(io_packet.cdb, srb->Cdb, sizeof(io_packet.cdb));
2056 io_packet.lun = 0;
2057
2058 if (srb->SrbFlags & SRB_FLAGS_NO_DATA_TRANSFER)
2059 {
2060 io_packet.data_buffer = NULL;
2061 io_packet.data_length = 0;
2062 }
2063 else
2064 {
2065 if ((irp->Flags & (IRP_READ_OPERATION | IRP_WRITE_OPERATION))
2066 && !(irp->Flags & IRP_PAGING_IO))
2067 {
2068 //
2069 // since these operations does not allign the buffer on page boundary
2070 // and some unknown traps in window NT, we have to copy to a buffer
2071 // we allocated
2072 io_packet.data_buffer = usb_alloc_mem(NonPagedPool, srb->DataTransferLength);
2073 if (irp->Flags & IRP_WRITE_OPERATION)
2074 {
2075 PULONG dest_buf, src_buf;
2076 ULONG i;
2077
2078 dest_buf = (PULONG) io_packet.data_buffer;
2079 src_buf = (PULONG) srb->DataBuffer;
2080
2081 if (src_buf && dest_buf)
2082 {
2083 for(i = 0; i < (srb->DataTransferLength >> 2); i++)
2084 {
2085 dest_buf[i] = src_buf[i];
2086 }
2087 }
2088 }
2089 }
2090 else
2091 io_packet.data_buffer = srb->DataBuffer;
2092
2093 io_packet.data_length = srb->DataTransferLength;
2094 }
2095
2096 if (io_packet.flags & IOP_FLAG_REQ_SENSE)
2097 {
2098 io_packet.sense_data = srb->SenseInfoBuffer;
2099 io_packet.sense_data_length = srb->SenseInfoBufferLength;
2100 }
2101
2102 io_packet.pirp = irp;
2103
2104 // do some conversions
2105 if (pdev_ext->pif_desc->bInterfaceSubClass == UMSS_SUBCLASS_SFF8070I)
2106 {
2107 if (umss_tsc_to_sff(&io_packet) == FALSE)
2108 {
2109 status = STATUS_DEVICE_PROTOCOL_ERROR;
2110
2111 usb_dbg_print(DBGLVL_MAXIMUM,
2112 ("umss_process_srb(): error converting to sff proto, 0x%x\n", status));
2113 srb->SrbStatus = SRB_STATUS_ERROR;
2114 break;
2115 }
2116 }
2117
2118 if (pdev_ext->pif_desc->bInterfaceProtocol == PROTOCOL_BULKONLY)
2119 {
2120 //
2121 // currently we support only transparent scsi command set
2122 //
2123 if (pdev_ext->pif_desc->bInterfaceSubClass == UMSS_SUBCLASS_SCSI_TCS ||
2124 pdev_ext->pif_desc->bInterfaceSubClass == UMSS_SUBCLASS_SFF8070I)
2125 status = umss_bulkonly_startio(pdev_ext, &io_packet);
2126 else
2127 status = STATUS_DEVICE_PROTOCOL_ERROR;
2128 }
2129 else if (pdev_ext->pif_desc->bInterfaceProtocol == PROTOCOL_CB
2130 || pdev_ext->pif_desc->bInterfaceProtocol == PROTOCOL_CBI)
2131 {
2132 status = umss_cbi_startio(pdev_ext, &io_packet);
2133 }
2134 else
2135 {
2136 status = STATUS_DEVICE_PROTOCOL_ERROR;
2137 }
2138
2139 if (status != STATUS_PENDING && status != STATUS_SUCCESS)
2140 {
2141 // error occured
2142 usb_dbg_print(DBGLVL_MAXIMUM, ("umss_process_srb(): error sending request, 0x%x\n", status));
2143 srb->SrbStatus = SRB_STATUS_ERROR;
2144 }
2145 break;
2146 }
2147 case SRB_FUNCTION_CLAIM_DEVICE:
2148 {
2149 srb->DataBuffer = (PVOID) dev_obj;
2150 }
2151 case SRB_FUNCTION_SHUTDOWN:
2152 case SRB_FUNCTION_FLUSH:
2153 case SRB_FUNCTION_RESET_BUS:
2154 case SRB_FUNCTION_FLUSH_QUEUE:
2155 case SRB_FUNCTION_RELEASE_QUEUE:
2156 case SRB_FUNCTION_RELEASE_DEVICE:
2157 default:
2158 {
2159 // for usb flash disk, they are luxurious
2160
2161 usb_dbg_print(DBGLVL_MAXIMUM, ("umss_process_srb(): current srb->Function=0x%x\n",
2162 srb->Function));
2163
2164 status = STATUS_SUCCESS;
2165 srb->SrbStatus = SRB_STATUS_SUCCESS;
2166 break;
2167 }
2168 }
2169
2170 usb_unlock_dev(pdev);
2171 pdev = NULL;
2172
2173 ERROR_OUT:
2174 irp->IoStatus.Status = status;
2175 if (status != STATUS_PENDING)
2176 {
2177 IoStartNextPacket(dev_obj, FALSE);
2178 IoCompleteRequest(irp, IO_NO_INCREMENT);
2179 }
2180
2181 //
2182 // UMSS_COMPLETE_START_IO( dev_obj, status, irp );
2183 //
2184 return status;
2185 }
2186
2187 BOOLEAN
2188 umss_tsc_to_sff(PIO_PACKET io_packet)
2189 {
2190 if (io_packet == NULL)
2191 return FALSE;
2192
2193 io_packet->cdb_length = 12;
2194 if (io_packet->cdb[0] == SCSIOP_MODE_SENSE)
2195 {
2196 io_packet->cdb[0] = 0x5a; // mode sense( 10 )
2197 io_packet->cdb[8] = io_packet->cdb[4];
2198 io_packet->cdb[4] = 0;
2199 if (io_packet->cdb[8] < 8)
2200 io_packet->cdb[8] = 8;
2201
2202 io_packet->data_length = 8;
2203 return TRUE;
2204 }
2205 if (io_packet->cdb[0] == SCSIOP_REASSIGN_BLOCKS ||
2206 io_packet->cdb[0] == SCSIOP_RESERVE_UNIT || io_packet->cdb[0] == SCSIOP_RELEASE_UNIT)
2207 return FALSE;
2208
2209 return TRUE;
2210 }
2211
2212 VOID
2213 umss_fix_sff_result(PIO_PACKET io_packet, SCSI_REQUEST_BLOCK *srb)
2214 {
2215 PBYTE buf;
2216 if (io_packet->cdb[0] != 0x5a)
2217 return;
2218 // the following is not right since it has to be 0x3f, return all pages
2219 // if( io_packet->cdb[ 2 ] != 0 )
2220 // return;
2221 srb->DataTransferLength = 4;
2222 buf = io_packet->data_buffer;
2223 // convert the mode param to scsi II
2224 buf[0] = buf[1];
2225 buf[1] = buf[2];
2226 buf[2] = buf[3];
2227 buf[3] = 0;
2228 return;
2229 }