add xpcu_close
[usb-driver] / xpcu.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <unistd.h>
4 #include <strings.h>
5 #include <usb.h>
6 #include "usb-driver.h"
7 #include "xpcu.h"
8
9 int xpcu_deviceinfo(struct xpcu_s *xpcu, unsigned char *buf) {
10 int i,j,k,l;
11 int len = 0;
12 WDU_CONFIGURATION **pConfigs, **pActiveConfig;
13 WDU_INTERFACE **pActiveInterface;
14
15 if (buf) {
16 struct usb_device_info *udi = (struct usb_device_info*)(buf+len);
17
18 udi->Descriptor.bLength = sizeof(WDU_DEVICE_DESCRIPTOR);
19 udi->Descriptor.bDescriptorType = xpcu->dev->descriptor.bDescriptorType;
20 udi->Descriptor.bcdUSB = xpcu->dev->descriptor.bcdUSB;
21 udi->Descriptor.bDeviceClass = xpcu->dev->descriptor.bDeviceClass;
22 udi->Descriptor.bDeviceSubClass = xpcu->dev->descriptor.bDeviceSubClass;
23 udi->Descriptor.bDeviceProtocol = xpcu->dev->descriptor.bDeviceProtocol;
24 udi->Descriptor.bMaxPacketSize0 = xpcu->dev->descriptor.bMaxPacketSize0;
25 udi->Descriptor.idVendor = xpcu->dev->descriptor.idVendor;
26 udi->Descriptor.idProduct = xpcu->dev->descriptor.idProduct;
27 udi->Descriptor.bcdDevice = xpcu->dev->descriptor.bcdDevice;
28 udi->Descriptor.iManufacturer = xpcu->dev->descriptor.iManufacturer;
29 udi->Descriptor.iProduct = xpcu->dev->descriptor.iProduct;
30 udi->Descriptor.iSerialNumber = xpcu->dev->descriptor.iSerialNumber;
31 udi->Descriptor.bNumConfigurations = xpcu->dev->descriptor.bNumConfigurations;
32
33 /* TODO: Fix Pipe0! */
34 udi->Pipe0.dwNumber = 0x00;
35 udi->Pipe0.dwMaximumPacketSize = xpcu->dev->descriptor.bMaxPacketSize0;
36 udi->Pipe0.type = 0;
37 udi->Pipe0.direction = WDU_DIR_IN_OUT;
38 udi->Pipe0.dwInterval = 0;
39
40 pConfigs = &(udi->pConfigs);
41 pActiveConfig = &(udi->pActiveConfig);
42 pActiveInterface = &(udi->pActiveInterface[0]);
43 }
44
45 len = sizeof(struct usb_device_info);
46
47 for (i=0; i<xpcu->dev->descriptor.bNumConfigurations; i++)
48 {
49 struct usb_config_descriptor *conf_desc = &xpcu->dev->config[i];
50 WDU_INTERFACE **pInterfaces;
51 WDU_ALTERNATE_SETTING **pAlternateSettings[conf_desc->bNumInterfaces];
52 WDU_ALTERNATE_SETTING **pActiveAltSetting[conf_desc->bNumInterfaces];
53
54 if (buf) {
55 WDU_CONFIGURATION *cfg = (WDU_CONFIGURATION*)(buf+len);
56
57 *pConfigs = cfg;
58 *pActiveConfig = cfg;
59
60 cfg->Descriptor.bLength = conf_desc->bLength;
61 cfg->Descriptor.bDescriptorType = conf_desc->bDescriptorType;
62 cfg->Descriptor.wTotalLength = conf_desc->wTotalLength;
63 cfg->Descriptor.bNumInterfaces = conf_desc->bNumInterfaces;
64 cfg->Descriptor.bConfigurationValue = conf_desc->bConfigurationValue;
65 cfg->Descriptor.iConfiguration = conf_desc->iConfiguration;
66 cfg->Descriptor.bmAttributes = conf_desc->bmAttributes;
67 cfg->Descriptor.MaxPower = conf_desc->MaxPower;
68
69 cfg->dwNumInterfaces = conf_desc->bNumInterfaces;
70
71 pInterfaces = &(cfg->pInterfaces);
72 }
73 len += sizeof(WDU_CONFIGURATION);
74
75 if (buf) {
76 *pInterfaces = (WDU_INTERFACE*)(buf+len);
77 for (j=0; j<conf_desc->bNumInterfaces; j++) {
78 WDU_INTERFACE *iface = (WDU_INTERFACE*)(buf+len);
79
80 pActiveInterface[j] = iface;
81
82 pAlternateSettings[j] = &(iface->pAlternateSettings);
83 iface->dwNumAltSettings = xpcu->dev->config[i].interface[j].num_altsetting;
84 pActiveAltSetting[j] = &(iface->pActiveAltSetting);
85
86 len += sizeof(WDU_INTERFACE);
87 }
88 } else {
89 len += sizeof(WDU_INTERFACE) * conf_desc->bNumInterfaces;
90 }
91
92 for (j=0; j<conf_desc->bNumInterfaces; j++)
93 {
94 struct usb_interface *interface = &xpcu->dev->config[i].interface[j];
95
96 if (buf) {
97 *pAlternateSettings[j] = (WDU_ALTERNATE_SETTING*)(buf+len);
98 /* FIXME: */
99 *pActiveAltSetting[j] = (WDU_ALTERNATE_SETTING*)(buf+len);
100 }
101
102 for(k=0; k<interface->num_altsetting; k++)
103 {
104 unsigned char bNumEndpoints = interface->altsetting[k].bNumEndpoints;
105 WDU_ENDPOINT_DESCRIPTOR **pEndpointDescriptors;
106 WDU_PIPE_INFO **pPipes;
107
108 if (buf) {
109 WDU_ALTERNATE_SETTING *altset = (WDU_ALTERNATE_SETTING*)(buf+len);
110
111 altset->Descriptor.bLength = interface->altsetting[k].bLength;
112 altset->Descriptor.bDescriptorType = interface->altsetting[k].bDescriptorType;
113 altset->Descriptor.bInterfaceNumber = interface->altsetting[k].bInterfaceNumber;
114 altset->Descriptor.bAlternateSetting = interface->altsetting[k].bAlternateSetting;
115 altset->Descriptor.bNumEndpoints = interface->altsetting[k].bNumEndpoints;
116 altset->Descriptor.bInterfaceClass = interface->altsetting[k].bInterfaceClass;
117 altset->Descriptor.bInterfaceSubClass = interface->altsetting[k].bInterfaceSubClass;
118 altset->Descriptor.bInterfaceProtocol = interface->altsetting[k].bInterfaceProtocol;
119 altset->Descriptor.iInterface = interface->altsetting[k].iInterface;
120 pEndpointDescriptors = &(altset->pEndpointDescriptors);
121 pPipes = &(altset->pPipes);
122
123 }
124 len +=sizeof(WDU_ALTERNATE_SETTING);
125
126 if (buf) {
127 *pEndpointDescriptors = (WDU_ENDPOINT_DESCRIPTOR*)(buf+len);
128 for (l = 0; l < bNumEndpoints; l++) {
129 WDU_ENDPOINT_DESCRIPTOR *ed = (WDU_ENDPOINT_DESCRIPTOR*)(buf+len);
130
131 ed->bLength = interface->altsetting[k].endpoint[l].bLength;
132 ed->bDescriptorType = interface->altsetting[k].endpoint[l].bDescriptorType;
133 ed->bEndpointAddress = interface->altsetting[k].endpoint[l].bEndpointAddress;
134 ed->bmAttributes = interface->altsetting[k].endpoint[l].bmAttributes;
135 ed->wMaxPacketSize = interface->altsetting[k].endpoint[l].wMaxPacketSize;
136 ed->bInterval = interface->altsetting[k].endpoint[l].bInterval;
137
138 len += sizeof(WDU_ENDPOINT_DESCRIPTOR);
139 }
140
141 *pPipes = (WDU_PIPE_INFO*)(buf+len);
142 for (l = 0; l < bNumEndpoints; l++) {
143 WDU_PIPE_INFO *pi = (WDU_PIPE_INFO*)(buf+len);
144
145 pi->dwNumber = interface->altsetting[k].endpoint[l].bEndpointAddress;
146 pi->dwMaximumPacketSize = WDU_GET_MAX_PACKET_SIZE(interface->altsetting[k].endpoint[l].wMaxPacketSize);
147 pi->type = interface->altsetting[k].endpoint[l].bmAttributes & USB_ENDPOINT_TYPE_MASK;
148 if (pi->type == PIPE_TYPE_CONTROL)
149 pi->direction = WDU_DIR_IN_OUT;
150 else
151 {
152 pi->direction = interface->altsetting[k].endpoint[l].bEndpointAddress & USB_ENDPOINT_DIR_MASK ? WDU_DIR_IN : WDU_DIR_OUT;
153 }
154
155 pi->dwInterval = interface->altsetting[k].endpoint[l].bInterval;
156
157 len += sizeof(WDU_PIPE_INFO);
158 }
159 } else {
160 len +=(sizeof(WDU_ENDPOINT_DESCRIPTOR)+sizeof(WDU_PIPE_INFO))*bNumEndpoints;
161 }
162 }
163 }
164 }
165
166 return len;
167 }
168
169 static int xpcu_claim(struct xpcu_s *xpcu, int claim) {
170 int ret = 0;
171 static int claimed = 0;
172
173 if (xpcu->interface < 0)
174 return -1;
175
176 if (claim == XPCU_CLAIM) {
177 if (claimed)
178 return 0;
179
180 ret = usb_claim_interface(xpcu->handle, xpcu->interface);
181 if (!ret) {
182 claimed = 1;
183 ret = usb_set_altinterface(xpcu->handle, xpcu->alternate);
184 if (ret)
185 fprintf(stderr, "usb_set_altinterface: %d\n", ret);
186 } else {
187 fprintf(stderr, "usb_claim_interface: %d -> %d (%s)\n",
188 xpcu->interface, ret, usb_strerror());
189 }
190 } else {
191 if (!claimed)
192 return 0;
193
194 ret = usb_release_interface(xpcu->handle, xpcu->interface);
195 if (!ret)
196 claimed = 0;
197 }
198
199 return ret;
200 }
201
202 int xpcu_transfer(struct xpcu_s *xpcu, struct usb_transfer *ut) {
203 int ret = 0;
204
205 xpcu_claim(xpcu, XPCU_CLAIM);
206 /* http://www.jungo.com/support/documentation/windriver/802/wdusb_man_mhtml/node55.html#SECTION001213000000000000000 */
207 if (ut->dwPipeNum == 0) { /* control pipe */
208 int requesttype, request, value, index, size;
209 requesttype = ut->SetupPacket[0];
210 request = ut->SetupPacket[1];
211 value = ut->SetupPacket[2] | (ut->SetupPacket[3] << 8);
212 index = ut->SetupPacket[4] | (ut->SetupPacket[5] << 8);
213 size = ut->SetupPacket[6] | (ut->SetupPacket[7] << 8);
214 DPRINTF("requesttype: %x, request: %x, value: %u, index: %u, size: %u\n", requesttype, request, value, index, size);
215 ret = usb_control_msg(xpcu->handle, requesttype, request, value, index, ut->pBuffer, size, ut->dwTimeout);
216 } else {
217 if (ut->fRead) {
218 ret = usb_bulk_read(xpcu->handle, ut->dwPipeNum, ut->pBuffer, ut->dwBufferSize, ut->dwTimeout);
219 } else {
220 ret = usb_bulk_write(xpcu->handle, ut->dwPipeNum, ut->pBuffer, ut->dwBufferSize, ut->dwTimeout);
221 }
222 xpcu_claim(xpcu, XPCU_RELEASE);
223 }
224
225 if (ret < 0) {
226 fprintf(stderr, "usb_transfer: %d (%s)\n", ret, usb_strerror());
227 } else {
228 ut->dwBytesTransferred = ret;
229 ret = 0;
230 }
231
232 return ret;
233 }
234
235 struct xpcu_s *xpcu_open(void) {
236 static struct xpcu_s xpcu;
237
238 bzero(&xpcu, sizeof(xpcu));
239 xpcu.interface = -1;
240 xpcu.alternate = -1;
241
242 usb_init();
243 usb_find_busses();
244 usb_find_devices();
245
246 xpcu.busses = usb_get_busses();
247
248 return &xpcu;
249 }
250
251 void xpcu_close(struct xpcu_s *xpcu) {
252 if (xpcu->handle) {
253 xpcu_claim(xpcu, XPCU_RELEASE);
254 usb_close(xpcu->handle);
255 }
256
257 xpcu->handle = NULL;
258 xpcu->interface = -1;
259 xpcu->alternate = -1;
260 }
Impressum, Datenschutz