PS2SDK
PS2 Homebrew Libraries
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 
13 static void fetchNextReportDescriptor(UsbdIoRequest_t *req);
14 static void requestDeviceDescriptor(UsbdIoRequest_t *req);
15 static void hubSetFuncAddress(void *userdata);
16 
17 static const char *usbdVersionString = "Version 1.6.0";
18 
19 void *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 
40 int 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 
63 UsbdEndpoint_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 
74 int 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 
81 int 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 
108 int 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 
132 static 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 
165 static 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 
175 static 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 
189 static void killDevice(UsbdDevice_t *dev, UsbdEndpoint_t *ep)
190 {
191  removeEndpointFromDevice(dev, ep);
192  checkDelayedResets(dev);
193  hubResetDevice(dev);
194 }
195 
196 static 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 
257 static 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 
283 static 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 
301 static void hubPeekDeviceDescriptor(void *userdata)
302 {
303  UsbdIoRequest_t *req;
304 
305  req = (UsbdIoRequest_t *)userdata;
306  req->m_length = 8;
307  requestDeviceDescriptor(req);
308 
309  // we've assigned a function address to the device and can reset the next device now, if there is one
310  checkDelayedResets(req->m_correspEndpoint->m_correspDevice);
311 }
312 
313 static void hubSetFuncAddressCB(UsbdIoRequest_t *req)
314 {
315  void *cb_arg;
316  UsbdDevice_t *dev;
317  void (*cb_func)(void *userdata);
318  int cb_delay;
319 
320  dev = req->m_correspEndpoint->m_correspDevice;
321  if ( req->m_resultCode == USB_RC_NORESPONSE )
322  {
323  dbg_printf("device not responding\n");
324  dev->m_functionDelay <<= 1;
325  if ( dev->m_functionDelay > 0x500 )
326  {
327  killDevice(dev, req->m_correspEndpoint);
328  return;
329  }
330  cb_func = hubSetFuncAddress;
331  cb_arg = req->m_correspEndpoint;
332  cb_delay = dev->m_functionDelay | 1;
333  }
334  else
335  {
336  cb_func = hubPeekDeviceDescriptor;
337  cb_arg = req;
338  cb_delay = 5;
339  req->m_correspEndpoint->m_hcEd->m_hcArea.stru.m_hcArea |= dev->m_functionAddress & 0x7F;
340  dev->m_deviceStatus = DEVICE_FETCHINGDESCRIPTOR;
341  }
342  addTimerCallback(&dev->m_timer, cb_func, cb_arg, cb_delay);
343 }
344 
345 static void hubSetFuncAddress(void *userdata)
346 {
347  UsbdEndpoint_t *ep;
348 
349  ep = (UsbdEndpoint_t *)userdata;
350  // dbg_printf("setting FA %02X\n", ep->m_correspDevice->m_functionAddress);
351  doControlTransfer(
352  ep,
353  &ep->m_correspDevice->m_ioRequest,
354  USB_DIR_OUT | USB_RECIP_DEVICE,
355  USB_REQ_SET_ADDRESS,
356  ep->m_correspDevice->m_functionAddress,
357  0,
358  0,
359  NULL,
360  hubSetFuncAddressCB);
361 }
362 
363 int hubTimedSetFuncAddress(UsbdDevice_t *dev)
364 {
365  dev->m_functionDelay = 20;
366  addTimerCallback(&dev->m_timer, hubSetFuncAddress, dev->m_endpointListStart, 21);
367  return 0;
368 }
369 
370 void flushPort(UsbdDevice_t *dev)
371 {
373  UsbdDevice_t *child;
374  int state;
375 
376  if ( dev->m_deviceStatus != DEVICE_NOTCONNECTED )
377  {
378  dev->m_deviceStatus = DEVICE_NOTCONNECTED;
379  if ( dev->m_devDriver )
380  callUsbDriverFunc(dev->m_devDriver->disconnect, dev->m_id, dev->m_devDriver->gp);
381  dev->m_devDriver = NULL;
382  if ( dev->m_timer.m_isActive )
383  cancelTimerCallback(&dev->m_timer);
384  while ( dev->m_endpointListStart )
385  {
386  removeEndpointFromDevice(dev, dev->m_endpointListStart);
387  }
388  for ( desc = dev->m_reportDescriptorStart; desc; desc = dev->m_reportDescriptorStart )
389  {
390  if ( desc->m_next )
391  desc->m_next->m_prev = desc->m_prev;
392  else
393  dev->m_reportDescriptorEnd = desc->m_prev;
394  if ( desc->m_prev )
395  desc->m_prev->m_next = desc->m_next;
396  else
397  dev->m_reportDescriptorStart = desc->m_next;
398  CpuSuspendIntr(&state);
399  FreeSysMemory(desc);
400  CpuResumeIntr(state);
401  }
402  while ( dev->m_childListStart )
403  {
404  child = dev->m_childListStart;
405  if ( child->m_next )
406  child->m_next->m_prev = child->m_prev;
407  else
408  dev->m_childListEnd = child->m_prev;
409  if ( child->m_prev )
410  child->m_prev->m_next = child->m_next;
411  else
412  dev->m_childListStart = child->m_next;
413  flushPort(child);
414  freeDevice(child);
415  }
416  dev->m_ioRequest.m_busyFlag = 0;
417  }
418  if ( dev->m_resetFlag )
419  checkDelayedResets(dev);
420 }
421 
422 int usbdInitInner(void)
423 {
424  printf("USB Driver (%s)", usbdVersionString);
425  printf("\n");
426  dbg_printf("HCD init...\n");
427  if ( initHcdStructs() < 0 )
428  return -1;
429  dbg_printf("Hub driver...\n");
430  if ( initHubDriver() < 0 )
431  return -1;
432  return 0;
433 }
UsbDeviceDescriptor
Definition: usbd.h:63
_usbdReportDescriptor
Definition: usbdpriv.h:298
USB_RC_OK
#define USB_RC_OK
Definition: usbd.h:238
request
Definition: thread.c:17
_UsbDriver
Definition: usbd.h:47
CpuSuspendIntr
int CpuSuspendIntr(int *state)
Definition: intrman.c:195
UsbEndpointDescriptor
Definition: usbd.h:108
count
u32 count
start sector of fragmented bd/file
Definition: usbhdfsd-common.h:3
_UsbDriver::name
char * name
Definition: usbd.h:51
usbdpriv.h
CpuResumeIntr
int CpuResumeIntr(int state)
Definition: intrman.c:217
UsbConfigDescriptor
Definition: usbd.h:81
USB_RC_BUSY
#define USB_RC_BUSY
Definition: usbd.h:287
_device
Definition: usbdpriv.h:107
USB_RC_NORESPONSE
#define USB_RC_NORESPONSE
Definition: usbd.h:248
_ioRequest
Definition: usbdpriv.h:82
_endpoint
Definition: usbdpriv.h:173