u3_scsi_spt.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. /**
  2. * u3_tool - U3 USB stick manager
  3. * Copyright (C) 2007 Daviedev, daviedev@users.sourceforge.net
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License along
  16. * with this program; if not, write to the Free Software Foundation, Inc.,
  17. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  18. */
  19. #include "u3_scsi.h"
  20. #include "u3_error.h"
  21. #include <sys/types.h>
  22. #include <sys/stat.h>
  23. #include <stdlib.h>
  24. #include <fcntl.h>
  25. #include <string.h>
  26. #include <unistd.h>
  27. #include <errno.h>
  28. #include <ctype.h>
  29. #include <windows.h>
  30. #include <ddk/ntddscsi.h>
  31. #define U3_TIMEOUT 2 // 2 seconds
  32. int u3_open(u3_handle_t *device, const char *which)
  33. {
  34. HANDLE hDevice;
  35. CHAR lpszDeviceName[7];
  36. DWORD dwBytesReturned;
  37. DWORD dwError;
  38. u3_set_error(device, "");
  39. device->dev = NULL;
  40. // check parameter
  41. if (strlen(which) != 1 || ! isalpha(which[0])) {
  42. u3_set_error(device, "Unknown drive name '%s', Expecting a "
  43. "drive letter", which);
  44. return U3_FAILURE;
  45. }
  46. //take the drive letter and put it in the format used in CreateFile
  47. memcpy(lpszDeviceName, (char *) "\\\\.\\*:", 7);
  48. lpszDeviceName[4] = which[0];
  49. //get a handle to the device, the parameters used here must be used in order for this to work
  50. hDevice=CreateFile(lpszDeviceName,
  51. GENERIC_READ|GENERIC_WRITE,
  52. FILE_SHARE_READ|FILE_SHARE_WRITE,
  53. NULL,
  54. OPEN_EXISTING,
  55. FILE_ATTRIBUTE_NORMAL,
  56. NULL);
  57. //if for some reason we couldn't get a handle to the device we will try again using slightly different parameters for CreateFile
  58. if (hDevice==INVALID_HANDLE_VALUE)
  59. {
  60. u3_set_error(device, "Failed openning handle for %s: Error %d\n", which, GetLastError());
  61. return U3_FAILURE;
  62. }
  63. device->dev = hDevice;
  64. return U3_SUCCESS;
  65. }
  66. void u3_close(u3_handle_t *device)
  67. {
  68. HANDLE hDevice = (HANDLE)device->dev;
  69. CloseHandle(hDevice);
  70. }
  71. int u3_send_cmd(u3_handle_t *device, uint8_t cmd[U3_CMD_LEN],
  72. int dxfer_direction, int dxfer_length, uint8_t *dxfer_data,
  73. uint8_t *status)
  74. {
  75. HANDLE hDevice = (HANDLE)device->dev;
  76. SCSI_PASS_THROUGH_DIRECT sptd;
  77. DWORD returned;
  78. BOOL err;
  79. // translate dxfer_direction
  80. switch (dxfer_direction) {
  81. case U3_DATA_NONE:
  82. dxfer_direction = SCSI_IOCTL_DATA_UNSPECIFIED;
  83. break;
  84. case U3_DATA_TO_DEV:
  85. dxfer_direction = SCSI_IOCTL_DATA_OUT;
  86. break;
  87. case U3_DATA_FROM_DEV:
  88. dxfer_direction = SCSI_IOCTL_DATA_IN;
  89. break;
  90. }
  91. // Prepare command
  92. memset(&sptd, 0, sizeof(SCSI_PASS_THROUGH_DIRECT));
  93. sptd.Length = sizeof(SCSI_PASS_THROUGH_DIRECT);// fixed
  94. sptd.CdbLength = U3_CMD_LEN; // length of command in bytes
  95. sptd.SenseInfoLength = 0; // don't use this currently...
  96. sptd.DataIn = dxfer_direction; // data direction
  97. sptd.DataTransferLength = dxfer_length; // Size of data transfered
  98. sptd.TimeOutValue = U3_TIMEOUT; // timeout in seconds
  99. sptd.DataBuffer = dxfer_data; // data buffer
  100. //sptd.SenseInfoOffset = offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS, sbuf);
  101. memcpy(sptd.Cdb, cmd, U3_CMD_LEN);
  102. // preform ioctl on device
  103. err = DeviceIoControl(hDevice, IOCTL_SCSI_PASS_THROUGH_DIRECT, &sptd,
  104. sizeof(sptd), &sptd, sizeof(sptd), &returned, NULL);
  105. // evaluate result
  106. if (!err) {
  107. u3_set_error(device, "Failed executing scsi command: "
  108. "Error %d", GetLastError());
  109. return U3_FAILURE;
  110. }
  111. *status = sptd.ScsiStatus;
  112. return U3_SUCCESS;
  113. }