PS2SDK
PS2 Homebrew Libraries
Loading...
Searching...
No Matches
device.c
1/*
2# _____ ___ ____ ___ ____
3# ____| | ____| | | |____|
4# | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
5#-----------------------------------------------------------------------
6# Copyright ps2dev - http://www.ps2dev.org
7# Licenced under Academic Free License version 2.0
8# Review ps2sdk README & LICENSE files for further details.
9*/
10
11#include "usbdpriv.h"
12
13static void fetchNextReportDescriptor(UsbdIoRequest_t *req);
14static void requestDeviceDescriptor(UsbdIoRequest_t *req);
15static void hubSetFuncAddress(UsbdEndpoint_t *ep);
16
17static const char *usbdVersionString = "Version 1.6.0";
18
19void *doGetDeviceStaticDescriptor(int devId, void *data, u8 type)
20{
21 UsbdDevice_t *dev;
22 UsbDeviceDescriptor *descBuf;
23
24 dev = fetchDeviceById(devId);
25 if ( !dev )
26 {
27 return NULL;
28 }
29 descBuf = data ? (UsbDeviceDescriptor *)((u8 *)data + ((UsbDeviceDescriptor *)data)->bLength) :
30 (UsbDeviceDescriptor *)dev->m_staticDeviceDescPtr;
31 for ( ; descBuf->bLength >= 2u && (u8 *)descBuf < (u8 *)dev->m_staticDeviceDescEndPtr;
32 descBuf = (UsbDeviceDescriptor *)((u8 *)descBuf + descBuf->bLength) )
33 {
34 if ( !type || descBuf->bDescriptorType == type )
35 return descBuf;
36 }
37 return NULL;
38}
39
40int doGetDeviceLocation(UsbdDevice_t *dev, u8 *path)
41{
42 const UsbdDevice_t *deviceTreeRoot;
43 int count;
44 int cpCount;
45 u8 tmpPath[16];
46
47 deviceTreeRoot = getDeviceTreeRoot();
48 for ( count = 0; count < 6 && dev != deviceTreeRoot; count += 1, dev = dev->m_parent )
49 {
50 tmpPath[count] = dev->m_attachedToPortNo;
51 }
52 if ( dev != deviceTreeRoot )
53 return USB_RC_BADHUBDEPTH;
54 if ( count >= 6 )
55 return USB_RC_BADHUBDEPTH;
56 for ( cpCount = 0; cpCount < 7; cpCount += 1 )
57 {
58 path[cpCount] = (cpCount < count) ? tmpPath[count - cpCount - 1] : 0;
59 }
60 return USB_RC_OK;
61}
62
63UsbdEndpoint_t *doOpenEndpoint(UsbdDevice_t *dev, const UsbEndpointDescriptor *endpDesc, u32 alignFlag)
64{
65 if ( !dev->m_parent )
66 {
67 return NULL;
68 }
69 if ( !endpDesc )
70 return dev->m_endpointListStart; // default control EP was already opened
71 return openDeviceEndpoint(dev, endpDesc, alignFlag);
72}
73
74int doCloseEndpoint(UsbdEndpoint_t *ep)
75{
76 if ( ep->m_correspDevice->m_endpointListStart == ep )
77 return 0;
78 return removeEndpointFromDevice(ep->m_correspDevice, ep);
79}
80
81int attachIoReqToEndpoint(UsbdEndpoint_t *ep, UsbdIoRequest_t *req, void *destdata, u16 length, void *callback)
82{
83 if ( !ep->m_correspDevice )
84 {
85 return USB_RC_BUSY;
86 }
87 if ( req->m_busyFlag )
88 {
89 return USB_RC_BUSY;
90 }
91 req->m_busyFlag = 1;
92 req->m_correspEndpoint = ep;
93 req->m_destPtr = destdata;
94 req->m_length = length;
95 req->m_resultCode = USB_RC_OK;
96 req->m_callbackProc = (InternCallback)callback;
97 req->m_prev = ep->m_ioReqListEnd;
98 if ( ep->m_ioReqListEnd )
99 ep->m_ioReqListEnd->m_next = req;
100 else
101 ep->m_ioReqListStart = req;
102 req->m_next = NULL;
103 ep->m_ioReqListEnd = req;
104 handleIoReqList(ep);
105 return USB_RC_OK;
106}
107
108int doControlTransfer(
109 UsbdEndpoint_t *ep,
110 UsbdIoRequest_t *req,
111 u8 requestType,
112 u8 request,
113 u16 value,
114 u16 index,
115 u16 length,
116 void *destdata,
117 void *callback)
118{
119 if ( req->m_busyFlag )
120 {
121 dbg_printf("ERROR: doControlTransfer: IoReq busy\n");
122 return USB_RC_BUSY;
123 }
124 req->m_devReq.requesttype = requestType;
125 req->m_devReq.request = request;
126 req->m_devReq.value = value;
127 req->m_devReq.index = index;
128 req->m_devReq.length = length;
129 return attachIoReqToEndpoint(ep, req, destdata, length, callback);
130}
131
132static void connectNewDevice(UsbdDevice_t *dev)
133{
134 sceUsbdLddOps *drv;
135
136 dbg_printf("searching driver for dev %d, FA %02X\n", dev->m_id, dev->m_functionAddress);
137 dev->m_deviceStatus = DEVICE_READY;
138 for ( drv = drvListStart; drv; drv = drv->next )
139 {
140 dev->m_privDataField = NULL;
141 if ( callUsbDriverFunc(drv->probe, dev->m_id, drv->gp) )
142 {
143 dev->m_devDriver = drv;
144 dbg_printf("Driver found (%s)\n", drv->name);
145 callUsbDriverFunc(drv->connect, dev->m_id, drv->gp);
146 return;
147 }
148 }
149 // No driver found yet. Call autoloader.
150 drv = drvAutoLoader;
151 if ( drv )
152 {
153 dev->m_privDataField = NULL;
154 if ( callUsbDriverFunc(drv->probe, dev->m_id, drv->gp) )
155 {
156 dev->m_devDriver = drv;
157 dbg_printf("(autoloader) Driver found (%s)\n", drv->name);
158 callUsbDriverFunc(drv->connect, dev->m_id, drv->gp);
159 return;
160 }
161 }
162 dbg_printf("no driver found\n");
163}
164
165static void fetchNextReportDescriptorCB(UsbdIoRequest_t *req)
166{
167 req->m_correspEndpoint->m_correspDevice->m_reportDescriptorCurForFetch =
168 req->m_correspEndpoint->m_correspDevice->m_reportDescriptorCurForFetch->m_next;
169 if ( req->m_correspEndpoint->m_correspDevice->m_reportDescriptorCurForFetch )
170 fetchNextReportDescriptor(req);
171 else
172 connectNewDevice(req->m_correspEndpoint->m_correspDevice);
173}
174
175static void fetchNextReportDescriptor(UsbdIoRequest_t *req)
176{
177 doControlTransfer(
178 req->m_correspEndpoint,
179 &req->m_correspEndpoint->m_correspDevice->m_ioRequest,
180 USB_DIR_IN | USB_RECIP_INTERFACE,
181 6u,
182 0x2200u,
183 req->m_correspEndpoint->m_correspDevice->m_reportDescriptorCurForFetch->m_ifNum,
184 req->m_correspEndpoint->m_correspDevice->m_reportDescriptorCurForFetch->m_length,
185 req->m_correspEndpoint->m_correspDevice->m_reportDescriptorCurForFetch->m_data,
186 fetchNextReportDescriptorCB);
187}
188
189static void killDevice(UsbdDevice_t *dev, UsbdEndpoint_t *ep)
190{
191 removeEndpointFromDevice(dev, ep);
192 checkDelayedResets(dev);
193 hubResetDevice(dev);
194}
195
196static void fetchConfigDescriptors(UsbdIoRequest_t *req)
197{
198 UsbdDevice_t *dev;
199 const UsbDeviceDescriptor *staticDeviceDescPtr;
200 int fetchDescriptorCounter;
201 u32 fetchDesc_1;
202 int fetchDesc_2;
203 int curDescNum_1;
204 UsbConfigDescriptor *destdata;
205 int readLen;
206
207 dev = req->m_correspEndpoint->m_correspDevice;
208 staticDeviceDescPtr = (UsbDeviceDescriptor *)dev->m_staticDeviceDescPtr;
209 if ( (int)dev->m_fetchDescriptorCounter > 0 && req->m_resultCode != USB_RC_OK )
210 {
211 killDevice(req->m_correspEndpoint->m_correspDevice, req->m_correspEndpoint);
212 return;
213 }
214 fetchDescriptorCounter = dev->m_fetchDescriptorCounter;
215 fetchDesc_1 = fetchDescriptorCounter + 1;
216 dev->m_fetchDescriptorCounter = fetchDesc_1;
217 fetchDesc_2 = fetchDescriptorCounter & 1;
218 curDescNum_1 = fetchDescriptorCounter >> 1;
219 destdata = (UsbConfigDescriptor *)dev->m_staticDeviceDescEndPtr;
220 if ( curDescNum_1 > 0 && !fetchDesc_2 )
221 dev->m_staticDeviceDescEndPtr = (u8 *)dev->m_staticDeviceDescEndPtr + READ_UINT16(&destdata->wTotalLength);
222 readLen = fetchDesc_2 ? READ_UINT16(&destdata->wTotalLength) : 4;
223 if ( (u8 *)dev->m_staticDeviceDescPtr + usbConfig.m_maxStaticDescSize < (u8 *)(&destdata->bLength + readLen) )
224 {
225 dbg_printf("USBD: UsbdDevice_t ignored, UsbdDevice_t descriptors too large\n");
226 return; // buffer is too small, silently ignore the device
227 }
228 if ( curDescNum_1 < staticDeviceDescPtr->bNumConfigurations )
229 {
230 doControlTransfer(
231 req->m_correspEndpoint,
232 &dev->m_ioRequest,
233 USB_DIR_IN | USB_RECIP_DEVICE,
234 USB_REQ_GET_DESCRIPTOR,
235 curDescNum_1 | (USB_DT_CONFIG << 8),
236 0,
237 readLen,
238 destdata,
239 fetchConfigDescriptors);
240 return;
241 }
242 dev->m_reportDescriptorStart = NULL;
243 if ( usbConfig.m_curDescNum )
244 {
245 handleStaticDeviceDescriptor(
246 dev, (UsbDeviceDescriptor *)dev->m_staticDeviceDescPtr, (UsbDeviceDescriptor *)dev->m_staticDeviceDescEndPtr);
247 if ( dev->m_reportDescriptorStart )
248 {
249 dev->m_reportDescriptorCurForFetch = dev->m_reportDescriptorStart;
250 fetchNextReportDescriptor(req);
251 return;
252 }
253 }
254 connectNewDevice(dev);
255}
256
257static void requestDeviceDescrptorCB(UsbdIoRequest_t *req)
258{
259 UsbdDevice_t *dev;
260 const UsbDeviceDescriptor *desc;
261
262 dev = req->m_correspEndpoint->m_correspDevice;
263 if ( req->m_resultCode != USB_RC_OK )
264 {
265 dbg_printf("unable to read device descriptor, err %d\n", req->m_resultCode);
266 killDevice(req->m_correspEndpoint->m_correspDevice, req->m_correspEndpoint);
267 return;
268 }
269 if ( req->m_transferedBytes >= sizeof(UsbDeviceDescriptor) )
270 {
271 dev->m_fetchDescriptorCounter = 0;
272 dev->m_staticDeviceDescEndPtr = &((UsbDeviceDescriptor *)dev->m_staticDeviceDescEndPtr)[1];
273 fetchConfigDescriptors(req);
274 return;
275 }
276 desc = dev->m_staticDeviceDescPtr;
277 req->m_correspEndpoint->m_hcEd->m_hcArea.stru.m_maxPacketSize =
278 (req->m_correspEndpoint->m_hcEd->m_hcArea.stru.m_maxPacketSize & 0xF800) | desc->bMaxPacketSize0;
279 req->m_length = sizeof(UsbDeviceDescriptor);
280 requestDeviceDescriptor(req);
281}
282
283static void requestDeviceDescriptor(UsbdIoRequest_t *req)
284{
285 UsbdDevice_t *dev;
286
287 dev = req->m_correspEndpoint->m_correspDevice;
288 dev->m_staticDeviceDescEndPtr = dev->m_staticDeviceDescPtr;
289 doControlTransfer(
290 req->m_correspEndpoint,
291 &dev->m_ioRequest,
292 USB_DIR_IN | USB_RECIP_DEVICE,
293 USB_REQ_GET_DESCRIPTOR,
294 USB_DT_DEVICE << 8,
295 0,
296 req->m_length,
297 dev->m_staticDeviceDescPtr,
298 requestDeviceDescrptorCB);
299}
300
301static void hubPeekDeviceDescriptor(UsbdIoRequest_t *req)
302{
303 req->m_length = 8;
304 requestDeviceDescriptor(req);
305
306 // we've assigned a function address to the device and can reset the next device now, if there is one
307 checkDelayedResets(req->m_correspEndpoint->m_correspDevice);
308}
309
310static void hubSetFuncAddressCB(UsbdIoRequest_t *req)
311{
312 void *cb_arg;
313 UsbdDevice_t *dev;
314 void (*cb_func)(void *);
315 int cb_delay;
316
317 dev = req->m_correspEndpoint->m_correspDevice;
318 if ( req->m_resultCode == USB_RC_NORESPONSE )
319 {
320 dbg_printf("device not responding\n");
321 dev->m_functionDelay <<= 1;
322 if ( dev->m_functionDelay > 0x500 )
323 {
324 killDevice(dev, req->m_correspEndpoint);
325 return;
326 }
327 cb_func = (void (*)(void *))hubSetFuncAddress;
328 cb_arg = req->m_correspEndpoint;
329 cb_delay = dev->m_functionDelay | 1;
330 }
331 else
332 {
333 cb_func = (void (*)(void *))hubPeekDeviceDescriptor;
334 cb_arg = req;
335 cb_delay = 5;
336 req->m_correspEndpoint->m_hcEd->m_hcArea.stru.m_hcArea |= dev->m_functionAddress & 0x7F;
337 dev->m_deviceStatus = DEVICE_FETCHINGDESCRIPTOR;
338 }
339 addTimerCallback(&dev->m_timer, cb_func, cb_arg, cb_delay);
340}
341
342static void hubSetFuncAddress(UsbdEndpoint_t *ep)
343{
344 // dbg_printf("setting FA %02X\n", ep->m_correspDevice->m_functionAddress);
345 doControlTransfer(
346 ep,
347 &ep->m_correspDevice->m_ioRequest,
348 USB_DIR_OUT | USB_RECIP_DEVICE,
349 USB_REQ_SET_ADDRESS,
350 ep->m_correspDevice->m_functionAddress,
351 0,
352 0,
353 NULL,
354 hubSetFuncAddressCB);
355}
356
357int hubTimedSetFuncAddress(UsbdDevice_t *dev)
358{
359 dev->m_functionDelay = 20;
360 addTimerCallback(&dev->m_timer, (TimerCallback)hubSetFuncAddress, dev->m_endpointListStart, 21);
361 return 0;
362}
363
364void flushPort(UsbdDevice_t *dev)
365{
367 UsbdDevice_t *child;
368 int state;
369
370 if ( dev->m_deviceStatus != DEVICE_NOTCONNECTED )
371 {
372 dev->m_deviceStatus = DEVICE_NOTCONNECTED;
373 if ( dev->m_devDriver )
374 callUsbDriverFunc(dev->m_devDriver->disconnect, dev->m_id, dev->m_devDriver->gp);
375 dev->m_devDriver = NULL;
376 if ( dev->m_timer.m_isActive )
377 cancelTimerCallback(&dev->m_timer);
378 while ( dev->m_endpointListStart )
379 {
380 removeEndpointFromDevice(dev, dev->m_endpointListStart);
381 }
382 for ( desc = dev->m_reportDescriptorStart; desc; desc = dev->m_reportDescriptorStart )
383 {
384 if ( desc->m_next )
385 desc->m_next->m_prev = desc->m_prev;
386 else
387 dev->m_reportDescriptorEnd = desc->m_prev;
388 if ( desc->m_prev )
389 desc->m_prev->m_next = desc->m_next;
390 else
391 dev->m_reportDescriptorStart = desc->m_next;
392 CpuSuspendIntr(&state);
393 FreeSysMemory(desc);
394 CpuResumeIntr(state);
395 }
396 while ( dev->m_childListStart )
397 {
398 child = dev->m_childListStart;
399 if ( child->m_next )
400 child->m_next->m_prev = child->m_prev;
401 else
402 dev->m_childListEnd = child->m_prev;
403 if ( child->m_prev )
404 child->m_prev->m_next = child->m_next;
405 else
406 dev->m_childListStart = child->m_next;
407 flushPort(child);
408 freeDevice(child);
409 }
410 dev->m_ioRequest.m_busyFlag = 0;
411 }
412 if ( dev->m_resetFlag )
413 checkDelayedResets(dev);
414}
415
416int usbdInitInner(void)
417{
418 printf("USB Driver (%s)", usbdVersionString);
419 printf("\n");
420 dbg_printf("HCD init...\n");
421 if ( initHcdStructs() < 0 )
422 return -1;
423 dbg_printf("Hub driver...\n");
424 if ( initHubDriver() < 0 )
425 return -1;
426 return 0;
427}
int CpuResumeIntr(int state)
Definition intrman.c:227
int CpuSuspendIntr(int *state)
Definition intrman.c:205
char * name
Definition usbd.h:51
#define USB_RC_OK
Definition usbd.h:238
#define USB_RC_BUSY
Definition usbd.h:287
#define USB_RC_NORESPONSE
Definition usbd.h:248
u32 count
start sector of fragmented bd/file