u3_scsi_usb.c 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352
  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 <sys/ioctl.h>
  24. #include <fcntl.h>
  25. #include <string.h>
  26. #include <unistd.h>
  27. #include <usb.h>
  28. #include <errno.h>
  29. #include <regex.h>
  30. // USB maximum packet length
  31. #define USB_MAX_PACKET_LEN 256
  32. // USB command block wrapper length
  33. #define U3_CBWCB_LEN 12
  34. // USB MSC command/status wrapper signatures
  35. #define CBW_SIGNATURE 0x43425355
  36. #define CSW_SIGNATURE 0x53425355
  37. // USB MSC command block wrapper data direction bits
  38. #define CBW_DATA_IN 0x80
  39. #define CBW_DATA_OUT 0x00
  40. #define CBW_DATA_NONE 0x00
  41. #define CBW_FLAG_DIRECTION 0x80
  42. #define U3_DEVICE_TIMEOUT 20000 //2000 millisecs == 2 seconds
  43. #define U3_DEV_LIST_LENGTH 2
  44. uint16_t u3_dev_list[U3_DEV_LIST_LENGTH][2] = {
  45. { 0x08ec, 0x0020 },
  46. { 0x0781, 0x5406 },
  47. };
  48. struct u3_usb_handle {
  49. usb_dev_handle *handle;
  50. int interface_num;
  51. int ep_out;
  52. int ep_in;
  53. };
  54. typedef struct u3_usb_handle u3_usb_handle_t;
  55. struct usb_msc_cbw {
  56. uint32_t dCBWSignature;
  57. uint32_t dCBWTag;
  58. uint32_t dCBWDataTransferLength;
  59. uint8_t bmCBWFlags;
  60. uint8_t bCBWLUN;
  61. uint8_t bCBWCBLength;
  62. uint8_t CBWCB[16];
  63. } __attribute__ ((packed));
  64. struct usb_msc_csw {
  65. uint32_t dCSWSignature;
  66. uint32_t dCSWTag;
  67. uint32_t dCSWDataResidue;
  68. uint8_t bCSWStatus;
  69. } __attribute__ ((packed));
  70. struct usb_device *
  71. locate_u3_device(uint16_t vid, uint16_t pid)
  72. {
  73. struct usb_bus *bus;
  74. struct usb_device *dev;
  75. // rescan busses and devices
  76. usb_find_busses();
  77. usb_find_devices();
  78. for (bus = usb_get_busses(); bus; bus = bus->next) {
  79. for (dev = bus->devices; dev; dev = dev->next) {
  80. if (dev->descriptor.idVendor == vid &&
  81. (dev->descriptor.idProduct == pid))
  82. {
  83. return dev;
  84. }
  85. }
  86. }
  87. return NULL;
  88. }
  89. int u3_open(u3_handle_t *device, const char *which)
  90. {
  91. uint16_t vid, pid;
  92. regex_t vid_pid_regex;
  93. struct usb_device *u3_device;
  94. u3_usb_handle_t *handle_wrapper;
  95. struct usb_config_descriptor *config_desc;
  96. struct usb_interface_descriptor *interface_desc;
  97. struct usb_endpoint_descriptor *endpoint_desc;
  98. int err;
  99. char errbuf[U3_MAX_ERROR_LEN];
  100. int i;
  101. // init
  102. u3_set_error(device, "");
  103. err = regcomp(&vid_pid_regex, "[::xdigit::]*:[::xdigit::]*", 0);
  104. if (err != 0) {
  105. regerror(err, &vid_pid_regex, errbuf, U3_MAX_ERROR_LEN);
  106. u3_set_error(device, "Failed constructing 'vid:pid' regular "
  107. "expression: %s", errbuf);
  108. return U3_FAILURE;
  109. }
  110. usb_init();
  111. if (debug)
  112. usb_set_debug(255);
  113. // Find device
  114. if (regexec(&vid_pid_regex, which, 0, 0, 0) == 0) {
  115. char *seperator=0;
  116. vid = strtoul(which, &seperator, 16);
  117. pid = strtoul(seperator+1, &seperator, 16);
  118. u3_device = locate_u3_device(vid, pid);
  119. } else if (strcmp(which, "scan") == 0) {
  120. i = 0;
  121. u3_device = NULL;
  122. while (u3_device == NULL && i < U3_DEV_LIST_LENGTH) {
  123. u3_device = locate_u3_device(u3_dev_list[i][0],
  124. u3_dev_list[i][1]);
  125. i++;
  126. }
  127. // } else if (regexec(&serial_regex, which, 0, 0, 0) == 0) {
  128. //TODO: search for a specific serial number
  129. } else {
  130. u3_set_error(device, "Unknown device name '%s', try 'scan' "
  131. "for first available device", which);
  132. return U3_FAILURE;
  133. }
  134. regfree(&vid_pid_regex);
  135. if (u3_device == NULL) {
  136. u3_set_error(device, "Could not locate the U3 device '%s', "
  137. "try 'scan' for first available device", which);
  138. return U3_FAILURE;
  139. }
  140. // Open device
  141. handle_wrapper = (u3_usb_handle_t *) malloc(sizeof(u3_usb_handle_t));
  142. if (handle_wrapper == NULL) {
  143. u3_set_error(device, "Failed allocate memory!!");
  144. return U3_FAILURE;
  145. }
  146. handle_wrapper->handle = usb_open(u3_device);
  147. // Set configuration
  148. if (u3_device->descriptor.bNumConfigurations != 1) {
  149. u3_set_error(device,
  150. "Multiple USB configuration not supported");
  151. goto open_fail;
  152. }
  153. config_desc = u3_device->config;
  154. usb_set_configuration(handle_wrapper->handle,
  155. config_desc->bConfigurationValue);
  156. // Claim device
  157. if (config_desc->bNumInterfaces != 1) {
  158. u3_set_error(device, "Multiple USB configuration interfaces "
  159. "not supported");
  160. goto open_fail;
  161. }
  162. if (config_desc->interface->num_altsetting != 1) {
  163. u3_set_error(device, "Multiple USB configuration interface "
  164. " alt. settings not supported");
  165. goto open_fail;
  166. }
  167. interface_desc = config_desc->interface->altsetting;
  168. handle_wrapper->interface_num = interface_desc->bInterfaceNumber;
  169. if ((err=usb_claim_interface(handle_wrapper->handle,
  170. handle_wrapper->interface_num)) != 0)
  171. {
  172. if (err == -EBUSY) {
  173. // Don't try to detach driver on Linux, this can cause
  174. // data loss and leaves the device in a unspecified
  175. // state. The user should 'unbind' the driver through
  176. // sysfs, or unload the usb-storage driver.
  177. u3_set_error(device, "Failed to claim device: Device is busy");
  178. goto open_fail;
  179. } else {
  180. u3_set_error(device, "Failed to claim device: %s", usb_strerror());
  181. goto open_fail;
  182. }
  183. }
  184. // Set alt. setting
  185. usb_set_altinterface(handle_wrapper->handle,
  186. interface_desc->bAlternateSetting);
  187. // Find the correct endpoints
  188. if (interface_desc->bNumEndpoints != 2) {
  189. u3_set_error(device, "Not exactly two usb endpoints defined,"
  190. " unsupported.");
  191. goto claimed_fail;
  192. }
  193. endpoint_desc = interface_desc->endpoint;
  194. if (endpoint_desc[0].bEndpointAddress & USB_ENDPOINT_DIR_MASK) {
  195. handle_wrapper->ep_in = endpoint_desc[0].bEndpointAddress;
  196. handle_wrapper->ep_out = endpoint_desc[1].bEndpointAddress;
  197. } else {
  198. handle_wrapper->ep_out = endpoint_desc[0].bEndpointAddress;
  199. handle_wrapper->ep_in = endpoint_desc[1].bEndpointAddress;
  200. }
  201. if (!((handle_wrapper->ep_in & USB_ENDPOINT_DIR_MASK) ^
  202. (handle_wrapper->ep_out & USB_ENDPOINT_DIR_MASK)))
  203. {
  204. u3_set_error(device, "Both usb endpoints in same direction!");
  205. goto claimed_fail;
  206. }
  207. device->dev = handle_wrapper;
  208. return U3_SUCCESS;
  209. claimed_fail:
  210. usb_release_interface(handle_wrapper->handle,
  211. handle_wrapper->interface_num);
  212. open_fail:
  213. usb_close(handle_wrapper->handle);
  214. free(handle_wrapper);
  215. return U3_FAILURE;
  216. }
  217. void u3_close(u3_handle_t *device)
  218. {
  219. u3_usb_handle_t *handle_wrapper = (u3_usb_handle_t *) device->dev;
  220. usb_release_interface(handle_wrapper->handle,
  221. handle_wrapper->interface_num);
  222. usb_close(handle_wrapper->handle);
  223. free(handle_wrapper);
  224. }
  225. int u3_send_cmd(u3_handle_t *device, uint8_t cmd[U3_CMD_LEN],
  226. int dxfer_direction, int dxfer_length, uint8_t *dxfer_data,
  227. uint8_t *status)
  228. {
  229. u3_usb_handle_t *handle_wrapper = (u3_usb_handle_t *) device->dev;
  230. struct usb_msc_cbw cbw;
  231. struct usb_msc_csw csw;
  232. // translate dxfer_direction
  233. switch (dxfer_direction) {
  234. case U3_DATA_TO_DEV:
  235. dxfer_direction = CBW_DATA_OUT;
  236. break;
  237. case U3_DATA_FROM_DEV:
  238. dxfer_direction = CBW_DATA_IN;
  239. break;
  240. case U3_DATA_NONE:
  241. default:
  242. dxfer_direction = CBW_DATA_NONE;
  243. dxfer_length = 0;
  244. break;
  245. }
  246. // Prepare command
  247. memset(&cbw, 0, sizeof(cbw));
  248. cbw.dCBWSignature = CBW_SIGNATURE;
  249. cbw.dCBWDataTransferLength = dxfer_length;
  250. cbw.bmCBWFlags |= (dxfer_direction & CBW_FLAG_DIRECTION);
  251. cbw.bCBWCBLength = U3_CBWCB_LEN;
  252. memcpy(&(cbw.CBWCB), cmd, U3_CBWCB_LEN);
  253. // send command
  254. if (usb_bulk_write(handle_wrapper->handle, handle_wrapper->ep_out,
  255. (char *) &cbw, sizeof(cbw), U3_DEVICE_TIMEOUT)
  256. != sizeof(cbw))
  257. {
  258. u3_set_error(device, "Failed executing scsi command: "
  259. "Could not write command block to device");
  260. return U3_FAILURE;
  261. }
  262. // read/write extra command data
  263. if (dxfer_direction == CBW_DATA_OUT) {
  264. int bytes_send = 0;
  265. while (bytes_send < dxfer_length) {
  266. int plen;
  267. plen = dxfer_length - bytes_send;
  268. if (plen > USB_MAX_PACKET_LEN)
  269. plen = USB_MAX_PACKET_LEN;
  270. if (usb_bulk_write(handle_wrapper->handle,
  271. handle_wrapper->ep_out,
  272. (char *) dxfer_data+bytes_send, plen,
  273. U3_DEVICE_TIMEOUT) != plen)
  274. {
  275. u3_set_error(device, "Failed executing scsi command: "
  276. "Could not write data to device");
  277. return U3_FAILURE;
  278. }
  279. bytes_send += plen;
  280. }
  281. } else if (dxfer_direction == CBW_DATA_IN) {
  282. if (usb_bulk_read(handle_wrapper->handle, handle_wrapper->ep_in,
  283. (char *) dxfer_data, dxfer_length,
  284. U3_DEVICE_TIMEOUT) != dxfer_length)
  285. {
  286. u3_set_error(device, "Failed executing scsi command: "
  287. "Could not read data from device");
  288. return U3_FAILURE;
  289. }
  290. }
  291. // read command status
  292. if (usb_bulk_read(handle_wrapper->handle, handle_wrapper->ep_in,
  293. (char *) &csw, sizeof(csw), U3_DEVICE_TIMEOUT)
  294. != sizeof(csw))
  295. {
  296. u3_set_error(device, "Failed executing scsi command: "
  297. "Could not read command status from device");
  298. return U3_FAILURE;
  299. }
  300. *status = csw.bCSWStatus;
  301. return U3_SUCCESS;
  302. }