2
0

usb-desc.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466
  1. #include "usb.h"
  2. #include "usb-desc.h"
  3. #include "trace.h"
  4. /* ------------------------------------------------------------------ */
  5. static uint8_t usb_lo(uint16_t val)
  6. {
  7. return val & 0xff;
  8. }
  9. static uint8_t usb_hi(uint16_t val)
  10. {
  11. return (val >> 8) & 0xff;
  12. }
  13. int usb_desc_device(const USBDescID *id, const USBDescDevice *dev,
  14. uint8_t *dest, size_t len)
  15. {
  16. uint8_t bLength = 0x12;
  17. if (len < bLength) {
  18. return -1;
  19. }
  20. dest[0x00] = bLength;
  21. dest[0x01] = USB_DT_DEVICE;
  22. dest[0x02] = usb_lo(dev->bcdUSB);
  23. dest[0x03] = usb_hi(dev->bcdUSB);
  24. dest[0x04] = dev->bDeviceClass;
  25. dest[0x05] = dev->bDeviceSubClass;
  26. dest[0x06] = dev->bDeviceProtocol;
  27. dest[0x07] = dev->bMaxPacketSize0;
  28. dest[0x08] = usb_lo(id->idVendor);
  29. dest[0x09] = usb_hi(id->idVendor);
  30. dest[0x0a] = usb_lo(id->idProduct);
  31. dest[0x0b] = usb_hi(id->idProduct);
  32. dest[0x0c] = usb_lo(id->bcdDevice);
  33. dest[0x0d] = usb_hi(id->bcdDevice);
  34. dest[0x0e] = id->iManufacturer;
  35. dest[0x0f] = id->iProduct;
  36. dest[0x10] = id->iSerialNumber;
  37. dest[0x11] = dev->bNumConfigurations;
  38. return bLength;
  39. }
  40. int usb_desc_device_qualifier(const USBDescDevice *dev,
  41. uint8_t *dest, size_t len)
  42. {
  43. uint8_t bLength = 0x0a;
  44. if (len < bLength) {
  45. return -1;
  46. }
  47. dest[0x00] = bLength;
  48. dest[0x01] = USB_DT_DEVICE_QUALIFIER;
  49. dest[0x02] = usb_lo(dev->bcdUSB);
  50. dest[0x03] = usb_hi(dev->bcdUSB);
  51. dest[0x04] = dev->bDeviceClass;
  52. dest[0x05] = dev->bDeviceSubClass;
  53. dest[0x06] = dev->bDeviceProtocol;
  54. dest[0x07] = dev->bMaxPacketSize0;
  55. dest[0x08] = dev->bNumConfigurations;
  56. dest[0x09] = 0; /* reserved */
  57. return bLength;
  58. }
  59. int usb_desc_config(const USBDescConfig *conf, uint8_t *dest, size_t len)
  60. {
  61. uint8_t bLength = 0x09;
  62. uint16_t wTotalLength = 0;
  63. int i, rc;
  64. if (len < bLength) {
  65. return -1;
  66. }
  67. dest[0x00] = bLength;
  68. dest[0x01] = USB_DT_CONFIG;
  69. dest[0x04] = conf->bNumInterfaces;
  70. dest[0x05] = conf->bConfigurationValue;
  71. dest[0x06] = conf->iConfiguration;
  72. dest[0x07] = conf->bmAttributes;
  73. dest[0x08] = conf->bMaxPower;
  74. wTotalLength += bLength;
  75. /* handle grouped interfaces if any*/
  76. for (i = 0; i < conf->nif_groups; i++) {
  77. rc = usb_desc_iface_group(&(conf->if_groups[i]),
  78. dest + wTotalLength,
  79. len - wTotalLength);
  80. if (rc < 0) {
  81. return rc;
  82. }
  83. wTotalLength += rc;
  84. }
  85. /* handle normal (ungrouped / no IAD) interfaces if any */
  86. for (i = 0; i < conf->nif; i++) {
  87. rc = usb_desc_iface(conf->ifs + i, dest + wTotalLength, len - wTotalLength);
  88. if (rc < 0) {
  89. return rc;
  90. }
  91. wTotalLength += rc;
  92. }
  93. dest[0x02] = usb_lo(wTotalLength);
  94. dest[0x03] = usb_hi(wTotalLength);
  95. return wTotalLength;
  96. }
  97. int usb_desc_iface_group(const USBDescIfaceAssoc *iad, uint8_t *dest,
  98. size_t len)
  99. {
  100. int pos = 0;
  101. int i = 0;
  102. /* handle interface association descriptor */
  103. uint8_t bLength = 0x08;
  104. if (len < bLength) {
  105. return -1;
  106. }
  107. dest[0x00] = bLength;
  108. dest[0x01] = USB_DT_INTERFACE_ASSOC;
  109. dest[0x02] = iad->bFirstInterface;
  110. dest[0x03] = iad->bInterfaceCount;
  111. dest[0x04] = iad->bFunctionClass;
  112. dest[0x05] = iad->bFunctionSubClass;
  113. dest[0x06] = iad->bFunctionProtocol;
  114. dest[0x07] = iad->iFunction;
  115. pos += bLength;
  116. /* handle associated interfaces in this group */
  117. for (i = 0; i < iad->nif; i++) {
  118. int rc = usb_desc_iface(&(iad->ifs[i]), dest + pos, len - pos);
  119. if (rc < 0) {
  120. return rc;
  121. }
  122. pos += rc;
  123. }
  124. return pos;
  125. }
  126. int usb_desc_iface(const USBDescIface *iface, uint8_t *dest, size_t len)
  127. {
  128. uint8_t bLength = 0x09;
  129. int i, rc, pos = 0;
  130. if (len < bLength) {
  131. return -1;
  132. }
  133. dest[0x00] = bLength;
  134. dest[0x01] = USB_DT_INTERFACE;
  135. dest[0x02] = iface->bInterfaceNumber;
  136. dest[0x03] = iface->bAlternateSetting;
  137. dest[0x04] = iface->bNumEndpoints;
  138. dest[0x05] = iface->bInterfaceClass;
  139. dest[0x06] = iface->bInterfaceSubClass;
  140. dest[0x07] = iface->bInterfaceProtocol;
  141. dest[0x08] = iface->iInterface;
  142. pos += bLength;
  143. for (i = 0; i < iface->ndesc; i++) {
  144. rc = usb_desc_other(iface->descs + i, dest + pos, len - pos);
  145. if (rc < 0) {
  146. return rc;
  147. }
  148. pos += rc;
  149. }
  150. for (i = 0; i < iface->bNumEndpoints; i++) {
  151. rc = usb_desc_endpoint(iface->eps + i, dest + pos, len - pos);
  152. if (rc < 0) {
  153. return rc;
  154. }
  155. pos += rc;
  156. }
  157. return pos;
  158. }
  159. int usb_desc_endpoint(const USBDescEndpoint *ep, uint8_t *dest, size_t len)
  160. {
  161. uint8_t bLength = 0x07;
  162. if (len < bLength) {
  163. return -1;
  164. }
  165. dest[0x00] = bLength;
  166. dest[0x01] = USB_DT_ENDPOINT;
  167. dest[0x02] = ep->bEndpointAddress;
  168. dest[0x03] = ep->bmAttributes;
  169. dest[0x04] = usb_lo(ep->wMaxPacketSize);
  170. dest[0x05] = usb_hi(ep->wMaxPacketSize);
  171. dest[0x06] = ep->bInterval;
  172. return bLength;
  173. }
  174. int usb_desc_other(const USBDescOther *desc, uint8_t *dest, size_t len)
  175. {
  176. int bLength = desc->length ? desc->length : desc->data[0];
  177. if (len < bLength) {
  178. return -1;
  179. }
  180. memcpy(dest, desc->data, bLength);
  181. return bLength;
  182. }
  183. /* ------------------------------------------------------------------ */
  184. static void usb_desc_setdefaults(USBDevice *dev)
  185. {
  186. const USBDesc *desc = dev->info->usb_desc;
  187. assert(desc != NULL);
  188. switch (dev->speed) {
  189. case USB_SPEED_LOW:
  190. case USB_SPEED_FULL:
  191. dev->device = desc->full;
  192. break;
  193. case USB_SPEED_HIGH:
  194. dev->device = desc->high;
  195. break;
  196. }
  197. dev->config = dev->device->confs;
  198. }
  199. void usb_desc_init(USBDevice *dev)
  200. {
  201. const USBDesc *desc = dev->info->usb_desc;
  202. assert(desc != NULL);
  203. dev->speed = USB_SPEED_FULL;
  204. dev->speedmask = 0;
  205. if (desc->full) {
  206. dev->speedmask |= USB_SPEED_MASK_FULL;
  207. }
  208. if (desc->high) {
  209. dev->speedmask |= USB_SPEED_MASK_HIGH;
  210. }
  211. usb_desc_setdefaults(dev);
  212. }
  213. void usb_desc_attach(USBDevice *dev)
  214. {
  215. const USBDesc *desc = dev->info->usb_desc;
  216. assert(desc != NULL);
  217. if (desc->high && (dev->port->speedmask & USB_SPEED_MASK_HIGH)) {
  218. dev->speed = USB_SPEED_HIGH;
  219. } else if (desc->full && (dev->port->speedmask & USB_SPEED_MASK_FULL)) {
  220. dev->speed = USB_SPEED_FULL;
  221. } else {
  222. fprintf(stderr, "usb: port/device speed mismatch for \"%s\"\n",
  223. dev->info->product_desc);
  224. return;
  225. }
  226. usb_desc_setdefaults(dev);
  227. }
  228. void usb_desc_set_string(USBDevice *dev, uint8_t index, const char *str)
  229. {
  230. USBDescString *s;
  231. QLIST_FOREACH(s, &dev->strings, next) {
  232. if (s->index == index) {
  233. break;
  234. }
  235. }
  236. if (s == NULL) {
  237. s = g_malloc0(sizeof(*s));
  238. s->index = index;
  239. QLIST_INSERT_HEAD(&dev->strings, s, next);
  240. }
  241. g_free(s->str);
  242. s->str = g_strdup(str);
  243. }
  244. const char *usb_desc_get_string(USBDevice *dev, uint8_t index)
  245. {
  246. USBDescString *s;
  247. QLIST_FOREACH(s, &dev->strings, next) {
  248. if (s->index == index) {
  249. return s->str;
  250. }
  251. }
  252. return NULL;
  253. }
  254. int usb_desc_string(USBDevice *dev, int index, uint8_t *dest, size_t len)
  255. {
  256. uint8_t bLength, pos, i;
  257. const char *str;
  258. if (len < 4) {
  259. return -1;
  260. }
  261. if (index == 0) {
  262. /* language ids */
  263. dest[0] = 4;
  264. dest[1] = USB_DT_STRING;
  265. dest[2] = 0x09;
  266. dest[3] = 0x04;
  267. return 4;
  268. }
  269. str = usb_desc_get_string(dev, index);
  270. if (str == NULL) {
  271. str = dev->info->usb_desc->str[index];
  272. if (str == NULL) {
  273. return 0;
  274. }
  275. }
  276. bLength = strlen(str) * 2 + 2;
  277. dest[0] = bLength;
  278. dest[1] = USB_DT_STRING;
  279. i = 0; pos = 2;
  280. while (pos+1 < bLength && pos+1 < len) {
  281. dest[pos++] = str[i++];
  282. dest[pos++] = 0;
  283. }
  284. return pos;
  285. }
  286. int usb_desc_get_descriptor(USBDevice *dev, int value, uint8_t *dest, size_t len)
  287. {
  288. const USBDesc *desc = dev->info->usb_desc;
  289. const USBDescDevice *other_dev;
  290. uint8_t buf[256];
  291. uint8_t type = value >> 8;
  292. uint8_t index = value & 0xff;
  293. int ret = -1;
  294. if (dev->speed == USB_SPEED_HIGH) {
  295. other_dev = dev->info->usb_desc->full;
  296. } else {
  297. other_dev = dev->info->usb_desc->high;
  298. }
  299. switch(type) {
  300. case USB_DT_DEVICE:
  301. ret = usb_desc_device(&desc->id, dev->device, buf, sizeof(buf));
  302. trace_usb_desc_device(dev->addr, len, ret);
  303. break;
  304. case USB_DT_CONFIG:
  305. if (index < dev->device->bNumConfigurations) {
  306. ret = usb_desc_config(dev->device->confs + index, buf, sizeof(buf));
  307. }
  308. trace_usb_desc_config(dev->addr, index, len, ret);
  309. break;
  310. case USB_DT_STRING:
  311. ret = usb_desc_string(dev, index, buf, sizeof(buf));
  312. trace_usb_desc_string(dev->addr, index, len, ret);
  313. break;
  314. case USB_DT_DEVICE_QUALIFIER:
  315. if (other_dev != NULL) {
  316. ret = usb_desc_device_qualifier(other_dev, buf, sizeof(buf));
  317. }
  318. trace_usb_desc_device_qualifier(dev->addr, len, ret);
  319. break;
  320. case USB_DT_OTHER_SPEED_CONFIG:
  321. if (other_dev != NULL && index < other_dev->bNumConfigurations) {
  322. ret = usb_desc_config(other_dev->confs + index, buf, sizeof(buf));
  323. buf[0x01] = USB_DT_OTHER_SPEED_CONFIG;
  324. }
  325. trace_usb_desc_other_speed_config(dev->addr, index, len, ret);
  326. break;
  327. case USB_DT_DEBUG:
  328. /* ignore silently */
  329. break;
  330. default:
  331. fprintf(stderr, "%s: %d unknown type %d (len %zd)\n", __FUNCTION__,
  332. dev->addr, type, len);
  333. break;
  334. }
  335. if (ret > 0) {
  336. if (ret > len) {
  337. ret = len;
  338. }
  339. memcpy(dest, buf, ret);
  340. }
  341. return ret;
  342. }
  343. int usb_desc_handle_control(USBDevice *dev, USBPacket *p,
  344. int request, int value, int index, int length, uint8_t *data)
  345. {
  346. const USBDesc *desc = dev->info->usb_desc;
  347. int i, ret = -1;
  348. assert(desc != NULL);
  349. switch(request) {
  350. case DeviceOutRequest | USB_REQ_SET_ADDRESS:
  351. dev->addr = value;
  352. trace_usb_set_addr(dev->addr);
  353. ret = 0;
  354. break;
  355. case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
  356. ret = usb_desc_get_descriptor(dev, value, data, length);
  357. break;
  358. case DeviceRequest | USB_REQ_GET_CONFIGURATION:
  359. data[0] = dev->config->bConfigurationValue;
  360. ret = 1;
  361. break;
  362. case DeviceOutRequest | USB_REQ_SET_CONFIGURATION:
  363. for (i = 0; i < dev->device->bNumConfigurations; i++) {
  364. if (dev->device->confs[i].bConfigurationValue == value) {
  365. dev->config = dev->device->confs + i;
  366. ret = 0;
  367. }
  368. }
  369. trace_usb_set_config(dev->addr, value, ret);
  370. break;
  371. case DeviceRequest | USB_REQ_GET_STATUS:
  372. data[0] = 0;
  373. if (dev->config->bmAttributes & 0x40) {
  374. data[0] |= 1 << USB_DEVICE_SELF_POWERED;
  375. }
  376. if (dev->remote_wakeup) {
  377. data[0] |= 1 << USB_DEVICE_REMOTE_WAKEUP;
  378. }
  379. data[1] = 0x00;
  380. ret = 2;
  381. break;
  382. case DeviceOutRequest | USB_REQ_CLEAR_FEATURE:
  383. if (value == USB_DEVICE_REMOTE_WAKEUP) {
  384. dev->remote_wakeup = 0;
  385. ret = 0;
  386. }
  387. trace_usb_clear_device_feature(dev->addr, value, ret);
  388. break;
  389. case DeviceOutRequest | USB_REQ_SET_FEATURE:
  390. if (value == USB_DEVICE_REMOTE_WAKEUP) {
  391. dev->remote_wakeup = 1;
  392. ret = 0;
  393. }
  394. trace_usb_set_device_feature(dev->addr, value, ret);
  395. break;
  396. }
  397. return ret;
  398. }