PS2SDK
PS2 Homebrew Libraries
usbd_api.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 int sceUsbdRegisterLdd(sceUsbdLddOps *driver)
14 {
15  void *OldGP;
16  int res;
17 
18 #if USE_GP_REGISTER
19  OldGP = SetModuleGP();
20 #else
21  OldGP = NULL;
22 #endif
23  res = USB_RC_BADCONTEXT;
24  if ( usbdLock() )
25  {
26 #if USE_GP_REGISTER
27  SetGP(OldGP);
28 #endif
29  return res;
30  }
31  res = doRegisterDriver(driver, OldGP);
32  usbdUnlock();
33 #if USE_GP_REGISTER
34  SetGP(OldGP);
35 #endif
36  return res;
37 }
38 
39 int sceUsbdRegisterAutoloader(sceUsbdLddOps *drv)
40 {
41  void *OldGP;
42  int res;
43 
44 #if USE_GP_REGISTER
45  OldGP = SetModuleGP();
46 #else
47  OldGP = NULL;
48 #endif
49  res = USB_RC_BADCONTEXT;
50  if ( usbdLock() )
51  {
52 #if USE_GP_REGISTER
53  SetGP(OldGP);
54 #endif
55  return res;
56  }
57  res = doRegisterAutoLoader(drv, OldGP);
58  usbdUnlock();
59 #if USE_GP_REGISTER
60  SetGP(OldGP);
61 #endif
62  return res;
63 }
64 
65 int sceUsbdUnregisterLdd(sceUsbdLddOps *driver)
66 {
67  void *OldGP;
68  int res;
69 
70 #if USE_GP_REGISTER
71  OldGP = SetModuleGP();
72 #else
73  OldGP = NULL;
74 #endif
75  res = USB_RC_BADCONTEXT;
76  if ( usbdLock() )
77  {
78 #if USE_GP_REGISTER
79  SetGP(OldGP);
80 #endif
81  return res;
82  }
83  res = doUnregisterDriver(driver);
84  usbdUnlock();
85 #if USE_GP_REGISTER
86  SetGP(OldGP);
87 #endif
88  return res;
89 }
90 
91 int sceUsbdUnregisterAutoloader(void)
92 {
93  void *OldGP;
94  int res;
95 
96 #if USE_GP_REGISTER
97  OldGP = SetModuleGP();
98 #else
99  OldGP = NULL;
100 #endif
101  res = USB_RC_BADCONTEXT;
102  if ( usbdLock() )
103  {
104 #if USE_GP_REGISTER
105  SetGP(OldGP);
106 #endif
107  return res;
108  }
109  res = doUnregisterAutoLoader();
110  usbdUnlock();
111 #if USE_GP_REGISTER
112  SetGP(OldGP);
113 #endif
114  return res;
115 }
116 
117 void *sceUsbdScanStaticDescriptor(int devId, void *data, u8 type)
118 {
119  void *OldGP;
120  const UsbdDevice_t *dev;
121  void *res;
122 
123 #if USE_GP_REGISTER
124  OldGP = SetModuleGP();
125 #else
126  OldGP = NULL;
127 #endif
128  res = NULL;
129  if ( usbdLock() )
130  {
131 #if USE_GP_REGISTER
132  SetGP(OldGP);
133 #endif
134  return res;
135  }
136  dev = fetchDeviceById(devId);
137  if ( dev && dev->m_deviceStatus == DEVICE_READY )
138  res = doGetDeviceStaticDescriptor(devId, data, type);
139  usbdUnlock();
140 #if USE_GP_REGISTER
141  SetGP(OldGP);
142 #endif
143  return res;
144 }
145 
146 int sceUsbdGetDeviceLocation(int devId, u8 *path)
147 {
148  void *OldGP;
149  int res;
150  UsbdDevice_t *dev;
151 
152 #if USE_GP_REGISTER
153  OldGP = SetModuleGP();
154 #else
155  OldGP = NULL;
156 #endif
157  res = USB_RC_BADCONTEXT;
158  if ( usbdLock() )
159  {
160 #if USE_GP_REGISTER
161  SetGP(OldGP);
162 #endif
163  return res;
164  }
165  res = USB_RC_BADDEV;
166  dev = fetchDeviceById(devId);
167  if ( dev && dev->m_deviceStatus == DEVICE_READY )
168  res = doGetDeviceLocation(dev, path);
169  usbdUnlock();
170 #if USE_GP_REGISTER
171  SetGP(OldGP);
172 #endif
173  return res;
174 }
175 
176 int sceUsbdSetPrivateData(int devId, void *data)
177 {
178  void *OldGP;
179  int res;
180  UsbdDevice_t *dev;
181 
182 #if USE_GP_REGISTER
183  OldGP = SetModuleGP();
184 #else
185  OldGP = NULL;
186 #endif
187  res = USB_RC_BADCONTEXT;
188  if ( usbdLock() )
189  {
190 #if USE_GP_REGISTER
191  SetGP(OldGP);
192 #endif
193  return res;
194  }
195  res = USB_RC_BADDEV;
196  dev = fetchDeviceById(devId);
197  if ( dev )
198  {
199  dev->m_privDataField = data;
200  res = USB_RC_OK;
201  }
202  usbdUnlock();
203 #if USE_GP_REGISTER
204  SetGP(OldGP);
205 #endif
206  return res;
207 }
208 
209 void *sceUsbdGetPrivateData(int devId)
210 {
211  void *OldGP;
212  void *res;
213  UsbdDevice_t *dev;
214 
215 #if USE_GP_REGISTER
216  OldGP = SetModuleGP();
217 #else
218  OldGP = NULL;
219 #endif
220  res = NULL;
221  if ( usbdLock() )
222  {
223 #if USE_GP_REGISTER
224  SetGP(OldGP);
225 #endif
226  return res;
227  }
228  dev = fetchDeviceById(devId);
229  if ( dev )
230  res = dev->m_privDataField;
231  usbdUnlock();
232 #if USE_GP_REGISTER
233  SetGP(OldGP);
234 #endif
235  return res;
236 }
237 
238 int sceUsbdOpenPipe(int devId, UsbEndpointDescriptor *desc)
239 {
240  void *OldGP;
241  UsbdDevice_t *dev;
242  int res;
243  const UsbdEndpoint_t *ep;
244 
245 #if USE_GP_REGISTER
246  OldGP = SetModuleGP();
247 #else
248  OldGP = NULL;
249 #endif
250  res = -1;
251  if ( usbdLock() )
252  {
253 #if USE_GP_REGISTER
254  SetGP(OldGP);
255 #endif
256  return res;
257  }
258  ep = NULL;
259  dev = fetchDeviceById(devId);
260  if ( dev )
261  ep = doOpenEndpoint(dev, desc, 0);
262  if ( ep )
263  res = ep->m_id;
264  usbdUnlock();
265 #if USE_GP_REGISTER
266  SetGP(OldGP);
267 #endif
268  return res;
269 }
270 
271 int sceUsbdOpenPipeAligned(int devId, UsbEndpointDescriptor *desc)
272 {
273  void *OldGP;
274  UsbdDevice_t *dev;
275  int res;
276  const UsbdEndpoint_t *ep;
277 
278 #if USE_GP_REGISTER
279  OldGP = SetModuleGP();
280 #else
281  OldGP = NULL;
282 #endif
283  res = -1;
284  if ( usbdLock() )
285  {
286 #if USE_GP_REGISTER
287  SetGP(OldGP);
288 #endif
289  return res;
290  }
291  ep = NULL;
292  dev = fetchDeviceById(devId);
293  if ( dev )
294  ep = doOpenEndpoint(dev, desc, 1u);
295  if ( ep )
296  res = ep->m_id;
297  usbdUnlock();
298 #if USE_GP_REGISTER
299  SetGP(OldGP);
300 #endif
301  return res;
302 }
303 
304 int sceUsbdClosePipe(int id)
305 {
306  void *OldGP;
307  UsbdEndpoint_t *ep;
308  int res;
309 
310 #if USE_GP_REGISTER
311  OldGP = SetModuleGP();
312 #else
313  OldGP = NULL;
314 #endif
315  res = USB_RC_BADCONTEXT;
316  if ( usbdLock() )
317  {
318 #if USE_GP_REGISTER
319  SetGP(OldGP);
320 #endif
321  return res;
322  }
323  res = USB_RC_BADPIPE;
324  ep = fetchEndpointById(id);
325  if ( ep )
326  res = doCloseEndpoint(ep);
327  usbdUnlock();
328 #if USE_GP_REGISTER
329  SetGP(OldGP);
330 #endif
331  return res;
332 }
333 
334 static void signalCallbackThreadFunc(UsbdIoRequest_t *req)
335 {
336  int state;
337 
338  CpuSuspendIntr(&state);
339  req->m_prev = cbListEnd;
340  if ( !cbListEnd )
341  cbListStart = req;
342  else
343  cbListEnd->m_next = req;
344  req->m_next = NULL;
345  cbListEnd = req;
346  CpuResumeIntr(state);
347  SetEventFlag(usbKernelResources.m_callbackEvent, 1u);
348 }
349 
350 static int usbdTransferPipeImpl(
351  void *gp_val,
352  int id,
353  void *data,
354  u32 length,
355  UsbDeviceRequest *option,
356  void *callback,
357  void *cbArg,
359 {
360  int res;
361  UsbdEndpoint_t *ep;
362  int bNumPackets;
363  UsbdIoRequest_t *req;
364 
365  res = USB_RC_BADCONTEXT;
366  if ( usbdLock() )
367  {
368  return res;
369  }
370  res = USB_RC_OK;
371  ep = fetchEndpointById(id);
372  if ( !ep )
373  {
374  dbg_printf("sceUsbdTransferPipe: UsbdEndpoint_t %d not found\n", id);
375  res = USB_RC_BADPIPE;
376  }
377  bNumPackets = 0;
378  if ( request && res == USB_RC_OK )
379  {
380  bNumPackets = request->bNumPackets;
381  data = request->bBufStart;
382  }
383  if ( request && res == USB_RC_OK )
384  {
385  if ( (unsigned int)(bNumPackets - 1) >= 8 || !data )
386  {
387  res = USB_RC_BADLENGTH;
388  }
389  }
390  if ( (request || (data && (int)length > 0)) && res == USB_RC_OK )
391  {
392  if ( ep->m_alignFlag && ((uiptr)data & 3) != 0 )
393  {
394  res = USB_RC_BADALIGN;
395  }
396  }
397  if ( request && res == USB_RC_OK )
398  {
399  if ( ep->m_endpointType != TYPE_ISOCHRON )
400  {
401  res = USB_RC_BADPIPE;
402  }
403  }
404  if ( request && res == USB_RC_OK )
405  {
406  int i_pkt;
407 
408  length = 0;
409  for ( i_pkt = 0; i_pkt < bNumPackets; i_pkt += 1 )
410  {
411  if ( (ep->m_hcEd->m_hcArea.stru.m_maxPacketSize & 0x7FFu) < request->Packets[i_pkt].bLength )
412  {
413  res = USB_RC_BADLENGTH;
414  break;
415  }
416  length += request->Packets[i_pkt].bLength;
417  if ( ep->m_alignFlag && (((((uiptr)data) & 0xFF) + (length & 0xFF)) & 3) != 0 )
418  {
419  res = USB_RC_BADALIGN;
420  break;
421  }
422  }
423  }
424  if ( (request || (data && (int)length > 0)) && res == USB_RC_OK )
425  {
426  if ( (((uiptr)data + length - 1) >> 12) - ((uiptr)data >> 12) >= 2 )
427  {
428  res = USB_RC_BADLENGTH;
429  }
430  }
431  if ( (!request && (data && (int)length > 0)) && res == USB_RC_OK )
432  {
433  switch ( ep->m_endpointType )
434  {
435  case TYPE_CONTROL:
436  {
437  if ( ((uiptr)data & 3) != 0 && (option->requesttype & 0x80) == 0 )
438  {
439  if ( (ep->m_hcEd->m_hcArea.stru.m_maxPacketSize & 0x7FF) == 64 && (int)length >= 63 )
440  {
441  res = USB_RC_BADALIGN;
442  }
443  }
444  break;
445  }
446  case TYPE_ISOCHRON:
447  {
448  if ( (ep->m_hcEd->m_hcArea.stru.m_maxPacketSize & 0x7FFu) < length )
449  {
450  res = USB_RC_BADLENGTH;
451  }
452  break;
453  }
454  default:
455  {
456  break;
457  }
458  }
459  }
460  if ( res == USB_RC_OK )
461  {
462  req = allocIoRequest();
463  if ( !req )
464  {
465  dbg_printf("Ran out of IoReqs\n");
466  res = USB_RC_IOREQ;
467  }
468  }
469  if ( res == USB_RC_OK )
470  {
471  req->m_userCallbackArg = cbArg;
472  req->m_gpSeg = gp_val;
473  req->m_req.bNumPackets = 0;
474  req->m_userCallbackProc = callback;
475  switch ( ep->m_endpointType )
476  {
477  case TYPE_ISOCHRON:
478  {
479  if ( request )
480  {
481  req->m_waitFrames = request->bRelStartFrame;
482  memcpy(&(req->m_req), request, sizeof(sceUsbdMultiIsochronousRequest));
483  }
484  else
485  {
486  req->m_waitFrames = (u32)option;
487  }
488  res = attachIoReqToEndpoint(ep, req, data, length, signalCallbackThreadFunc);
489  break;
490  }
491  case TYPE_CONTROL:
492  {
493  if ( !option )
494  {
495  freeIoRequest(req);
496  res = USB_RC_BADOPTION;
497  }
498  if ( res == USB_RC_OK )
499  {
500  if ( option->length != length )
501  {
502  freeIoRequest(req);
503  res = USB_RC_BADLENGTH;
504  }
505  }
506  if ( res == USB_RC_OK )
507  {
508  res = doControlTransfer(
509  ep,
510  req,
511  option->requesttype,
512  option->request,
513  option->value,
514  option->index,
515  option->length,
516  data,
517  signalCallbackThreadFunc);
518  }
519  break;
520  }
521  default:
522  {
523  res = attachIoReqToEndpoint(ep, req, data, length, signalCallbackThreadFunc);
524  break;
525  }
526  }
527  }
528  usbdUnlock();
529  return res;
530 }
531 
532 int sceUsbdTransferPipe(int id, void *data, u32 len, void *option, sceUsbdDoneCallback callback, void *cbArg)
533 {
534  void *OldGP;
535  int res;
536 
537 #if USE_GP_REGISTER
538  OldGP = SetModuleGP();
539 #else
540  OldGP = NULL;
541 #endif
542  res = usbdTransferPipeImpl(OldGP, id, data, len, (UsbDeviceRequest *)option, callback, cbArg, NULL);
543 #if USE_GP_REGISTER
544  SetGP(OldGP);
545 #endif
546  return res;
547 }
548 
549 int sceUsbdMultiIsochronousTransfer(
550  int pipeId, sceUsbdMultiIsochronousRequest *request, sceUsbdMultiIsochronousDoneCallback callback, void *cbArg)
551 {
552  void *OldGP;
553  int res;
554 
555 #if USE_GP_REGISTER
556  OldGP = SetModuleGP();
557 #else
558  OldGP = NULL;
559 #endif
560  res = usbdTransferPipeImpl(OldGP, pipeId, NULL, 0, NULL, callback, cbArg, request);
561 #if USE_GP_REGISTER
562  SetGP(OldGP);
563 #endif
564  return res;
565 }
566 
567 int sceUsbdChangeThreadPriority(int prio1, int prio2)
568 {
569  void *OldGP;
570  int res;
571 
572 #if USE_GP_REGISTER
573  OldGP = SetModuleGP();
574 #else
575  OldGP = NULL;
576 #endif
577  res = 0;
578  if ( usbConfig.m_hcdThreadPrio != prio1 )
579  {
580  usbConfig.m_hcdThreadPrio = prio1;
581  res = ChangeThreadPriority(usbKernelResources.m_hcdTid, prio1);
582  }
583  if ( res == 0 && usbConfig.m_cbThreadPrio != prio2 )
584  {
585  usbConfig.m_cbThreadPrio = prio2;
586  res = ChangeThreadPriority(usbKernelResources.m_callbackTid, prio2);
587  }
588 #if USE_GP_REGISTER
589  SetGP(OldGP);
590 #endif
591  return res;
592 }
593 
594 int sceUsbdGetReportDescriptor(int devId, int cfgNum, int ifNum, void **desc, u32 *len)
595 {
596  void *OldGP;
597  int res;
598  UsbdDevice_t *dev;
599  UsbdReportDescriptor_t *hidDescriptorStart;
600 
601 #if USE_GP_REGISTER
602  OldGP = SetModuleGP();
603 #else
604  OldGP = NULL;
605 #endif
606  res = USB_RC_BADCONTEXT;
607  if ( usbdLock() )
608  {
609 #if USE_GP_REGISTER
610  SetGP(OldGP);
611 #endif
612  return res;
613  }
614  res = USB_RC_BADDEV;
615  hidDescriptorStart = NULL;
616  dev = fetchDeviceById(devId);
617  if ( dev )
618  {
619  res = USB_RC_UNKNOWN;
620  for ( hidDescriptorStart = dev->m_reportDescriptorStart;
621  hidDescriptorStart
622  && ((int)hidDescriptorStart->m_cfgNum != cfgNum || (int)hidDescriptorStart->m_ifNum != ifNum);
623  hidDescriptorStart = hidDescriptorStart->m_next )
624  {
625  }
626  }
627  if ( hidDescriptorStart )
628  {
629  res = USB_RC_OK;
630  if ( desc )
631  *desc = hidDescriptorStart->m_data;
632  if ( len )
633  *len = hidDescriptorStart->m_length;
634  }
635  usbdUnlock();
636 #if USE_GP_REGISTER
637  SetGP(OldGP);
638 #endif
639  return res;
640 }
_usbdReportDescriptor
Definition: usbdpriv.h:298
USB_RC_OK
#define USB_RC_OK
Definition: usbd.h:238
request
Definition: thread.c:17
sceUsbdMultiIsochronousRequest
Definition: usbd.h:152
_UsbDriver
Definition: usbd.h:47
CpuSuspendIntr
int CpuSuspendIntr(int *state)
Definition: intrman.c:195
UsbEndpointDescriptor
Definition: usbd.h:108
UsbDeviceRequest
Definition: usbd.h:22
USB_RC_BADDEV
#define USB_RC_BADDEV
Definition: usbd.h:267
usbdpriv.h
CpuResumeIntr
int CpuResumeIntr(int state)
Definition: intrman.c:217
USB_RC_BADPIPE
#define USB_RC_BADPIPE
Definition: usbd.h:269
USB_RC_BADCONTEXT
#define USB_RC_BADCONTEXT
Definition: usbd.h:275
USB_RC_BADOPTION
#define USB_RC_BADOPTION
Definition: usbd.h:284
_device
Definition: usbdpriv.h:107
USB_RC_IOREQ
#define USB_RC_IOREQ
Definition: usbd.h:282
USB_RC_BADLENGTH
#define USB_RC_BADLENGTH
Definition: usbd.h:271
USB_RC_UNKNOWN
#define USB_RC_UNKNOWN
Definition: usbd.h:294
_ioRequest
Definition: usbdpriv.h:82
_endpoint
Definition: usbdpriv.h:173