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