microblaze/s3adsp_1800: Define macros for irq map
[qemu.git] / hw / usb / desc-msos.c
blobed8d62cab89da23ba0bf515ef3e3c087b4f8a9a4
1 #include "hw/usb.h"
2 #include "hw/usb/desc.h"
4 /*
5 * Microsoft OS Descriptors
7 * Windows tries to fetch some special descriptors with informations
8 * specifically for windows. Presence is indicated using a special
9 * string @ index 0xee. There are two kinds of descriptors:
11 * compatid descriptor
12 * Used to bind drivers, if usb class isn't specific enougth.
13 * Used for PTP/MTP for example (both share the same usb class).
15 * properties descriptor
16 * Does carry registry entries. They show up in
17 * HLM\SYSTEM\CurrentControlSet\Enum\USB\<devid>\<serial>\Device Parameters
19 * Note that Windows caches the stuff it got in the registry, so when
20 * playing with this you have to delete registry subtrees to make
21 * windows query the device again:
22 * HLM\SYSTEM\CurrentControlSet\Control\usbflags
23 * HLM\SYSTEM\CurrentControlSet\Enum\USB
24 * Windows will complain it can't delete entries on the second one.
25 * It has deleted everything it had permissions too, which is enouth
26 * as this includes "Device Parameters".
28 * http://msdn.microsoft.com/en-us/library/windows/hardware/ff537430.aspx
32 /* ------------------------------------------------------------------ */
34 typedef struct msos_compat_hdr {
35 uint32_t dwLength;
36 uint8_t bcdVersion_lo;
37 uint8_t bcdVersion_hi;
38 uint8_t wIndex_lo;
39 uint8_t wIndex_hi;
40 uint8_t bCount;
41 uint8_t reserved[7];
42 } QEMU_PACKED msos_compat_hdr;
44 typedef struct msos_compat_func {
45 uint8_t bFirstInterfaceNumber;
46 uint8_t reserved_1;
47 uint8_t compatibleId[8];
48 uint8_t subCompatibleId[8];
49 uint8_t reserved_2[6];
50 } QEMU_PACKED msos_compat_func;
52 static int usb_desc_msos_compat(const USBDesc *desc, uint8_t *dest)
54 msos_compat_hdr *hdr = (void *)dest;
55 msos_compat_func *func;
56 int length = sizeof(*hdr);
57 int count = 0;
59 func = (void *)(dest + length);
60 func->bFirstInterfaceNumber = 0;
61 func->reserved_1 = 0x01;
62 length += sizeof(*func);
63 count++;
65 hdr->dwLength = cpu_to_le32(length);
66 hdr->bcdVersion_lo = 0x00;
67 hdr->bcdVersion_hi = 0x01;
68 hdr->wIndex_lo = 0x04;
69 hdr->wIndex_hi = 0x00;
70 hdr->bCount = count;
71 return length;
74 /* ------------------------------------------------------------------ */
76 typedef struct msos_prop_hdr {
77 uint32_t dwLength;
78 uint8_t bcdVersion_lo;
79 uint8_t bcdVersion_hi;
80 uint8_t wIndex_lo;
81 uint8_t wIndex_hi;
82 uint8_t wCount_lo;
83 uint8_t wCount_hi;
84 } QEMU_PACKED msos_prop_hdr;
86 typedef struct msos_prop {
87 uint32_t dwLength;
88 uint32_t dwPropertyDataType;
89 uint8_t dwPropertyNameLength_lo;
90 uint8_t dwPropertyNameLength_hi;
91 uint8_t bPropertyName[];
92 } QEMU_PACKED msos_prop;
94 typedef struct msos_prop_data {
95 uint32_t dwPropertyDataLength;
96 uint8_t bPropertyData[];
97 } QEMU_PACKED msos_prop_data;
99 typedef enum msos_prop_type {
100 MSOS_REG_SZ = 1,
101 MSOS_REG_EXPAND_SZ = 2,
102 MSOS_REG_BINARY = 3,
103 MSOS_REG_DWORD_LE = 4,
104 MSOS_REG_DWORD_BE = 5,
105 MSOS_REG_LINK = 6,
106 MSOS_REG_MULTI_SZ = 7,
107 } msos_prop_type;
109 static int usb_desc_msos_prop_name(struct msos_prop *prop,
110 const wchar_t *name)
112 int length = wcslen(name) + 1;
113 int i;
115 prop->dwPropertyNameLength_lo = usb_lo(length*2);
116 prop->dwPropertyNameLength_hi = usb_hi(length*2);
117 for (i = 0; i < length; i++) {
118 prop->bPropertyName[i*2] = usb_lo(name[i]);
119 prop->bPropertyName[i*2+1] = usb_hi(name[i]);
121 return length*2;
124 static int usb_desc_msos_prop_str(uint8_t *dest, msos_prop_type type,
125 const wchar_t *name, const wchar_t *value)
127 struct msos_prop *prop = (void *)dest;
128 struct msos_prop_data *data;
129 int length = sizeof(*prop);
130 int i, vlen = wcslen(value) + 1;
132 prop->dwPropertyDataType = cpu_to_le32(type);
133 length += usb_desc_msos_prop_name(prop, name);
134 data = (void *)(dest + length);
136 data->dwPropertyDataLength = cpu_to_le32(vlen*2);
137 length += sizeof(*prop);
139 for (i = 0; i < vlen; i++) {
140 data->bPropertyData[i*2] = usb_lo(value[i]);
141 data->bPropertyData[i*2+1] = usb_hi(value[i]);
143 length += vlen*2;
145 prop->dwLength = cpu_to_le32(length);
146 return length;
149 static int usb_desc_msos_prop_dword(uint8_t *dest, const wchar_t *name,
150 uint32_t value)
152 struct msos_prop *prop = (void *)dest;
153 struct msos_prop_data *data;
154 int length = sizeof(*prop);
156 prop->dwPropertyDataType = cpu_to_le32(MSOS_REG_DWORD_LE);
157 length += usb_desc_msos_prop_name(prop, name);
158 data = (void *)(dest + length);
160 data->dwPropertyDataLength = cpu_to_le32(4);
161 data->bPropertyData[0] = (value) & 0xff;
162 data->bPropertyData[1] = (value >> 8) & 0xff;
163 data->bPropertyData[2] = (value >> 16) & 0xff;
164 data->bPropertyData[3] = (value >> 24) & 0xff;
165 length += sizeof(*prop) + 4;
167 prop->dwLength = cpu_to_le32(length);
168 return length;
171 static int usb_desc_msos_prop(const USBDesc *desc, uint8_t *dest)
173 msos_prop_hdr *hdr = (void *)dest;
174 int length = sizeof(*hdr);
175 int count = 0;
177 if (desc->msos->Label) {
179 * Given as example in the specs. Havn't figured yet where
180 * this label shows up in the windows gui.
182 length += usb_desc_msos_prop_str(dest+length, MSOS_REG_SZ,
183 L"Label", desc->msos->Label);
184 count++;
187 if (desc->msos->SelectiveSuspendEnabled) {
189 * Signaling remote wakeup capability in the standard usb
190 * descriptors isn't enouth to make windows actually use it.
191 * This is the "Yes, we really mean it" registy entry to flip
192 * the switch in the windows drivers.
194 length += usb_desc_msos_prop_dword(dest+length,
195 L"SelectiveSuspendEnabled", 1);
196 count++;
199 hdr->dwLength = cpu_to_le32(length);
200 hdr->bcdVersion_lo = 0x00;
201 hdr->bcdVersion_hi = 0x01;
202 hdr->wIndex_lo = 0x05;
203 hdr->wIndex_hi = 0x00;
204 hdr->wCount_lo = usb_lo(count);
205 hdr->wCount_hi = usb_hi(count);
206 return length;
209 /* ------------------------------------------------------------------ */
211 int usb_desc_msos(const USBDesc *desc, USBPacket *p,
212 int index, uint8_t *dest, size_t len)
214 void *buf = g_malloc0(4096);
215 int length = 0;
217 switch (index) {
218 case 0x0004:
219 length = usb_desc_msos_compat(desc, buf);
220 break;
221 case 0x0005:
222 length = usb_desc_msos_prop(desc, buf);
223 break;
226 if (length > len) {
227 length = len;
229 memcpy(dest, buf, length);
230 free(buf);
232 p->actual_length = length;
233 return 0;