PS2SDK
PS2 Homebrew Libraries
Loading...
Searching...
No Matches
usbd_main.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#ifdef _IOP
14IRX_ID("USB_driver", 2, 4);
15#endif
16// Based on the module from SCE SDK 3.1.0.
17
18static int usbdModuleUnload(void);
19
20extern struct irx_export_table _exp_usbd;
21
22static UsbdArgOption_t SupportedArgs[] = {
23 {"dev=", &usbConfig.m_maxDevices, NULL},
24 {"ed=", &usbConfig.m_maxEndpoints, NULL},
25 {"gtd=", &usbConfig.m_maxTransfDesc, NULL},
26 {"itd=", &usbConfig.m_maxIsoTransfDesc, NULL},
27 {"ioreq=", &usbConfig.m_maxIoReqs, NULL},
28 {"conf=", &usbConfig.m_maxStaticDescSize, NULL},
29 {"hub=", &usbConfig.m_maxHubDevices, NULL},
30 {"port=", &usbConfig.m_maxPortsPerHub, NULL},
31 {"thpri=", &usbConfig.m_hcdThreadPrio, &usbConfig.m_cbThreadPrio},
32 {"reportd=", &usbConfig.m_curDescNum, NULL},
33 {NULL, NULL, NULL}};
34
35UsbdMemoryPool_t *memPool = NULL;
36UsbdKernelResources_t usbKernelResources = {-1, -1, -1, -1, -1};
37UsbdIoRequest_t *cbListStart = NULL;
38UsbdIoRequest_t *cbListEnd = NULL;
39#ifndef MINI_DRIVER
40UsbdConfig_t usbConfig = {
41 0x20,
42 0x40,
43 0x80,
44 0x80,
45 0x100,
46 0x200,
47 0x8,
48 0x8,
49 0x0,
50 0x1E,
51 0x24,
52 0x0,
53};
54#else
55UsbdConfig_t usbConfig = {
56 0x10,
57 0x20,
58 0x40,
59 0x40,
60 0x100,
61 0x200,
62 0x4,
63 0x4,
64 0x0,
65 0x1E,
66 0x24,
67 0x0,
68};
69#endif
70sceUsbdLddOps *drvListStart = NULL;
71sceUsbdLddOps *drvListEnd = NULL;
72sceUsbdLddOps *drvAutoLoader = NULL;
73
74static int usbdIntrHandler(void *arg)
75{
76 const UsbdKernelResources_t *kernelResources;
77
78 kernelResources = (UsbdKernelResources_t *)arg;
79 iSetEventFlag(kernelResources->m_hcdIrqEvent, 1u);
80 return 0;
81}
82
83static void hcdIrqThread(void *arg)
84{
85 u32 efres;
86
87 (void)arg;
88 while ( 1 )
89 {
90 WaitEventFlag(usbKernelResources.m_hcdIrqEvent, 1u, WEF_OR | WEF_CLEAR, &efres);
91 usbdLock();
92 hcdProcessIntr();
93 EnableIntr(IOP_IRQ_USB);
94 PostIntrEnableFunction();
95 usbdUnlock();
96 }
97}
98
99static void callbackThreadFunc(void *arg)
100{
101 UsbdIoRequest_t *req;
102 UsbdIoRequest_t reqCopy;
103 u32 efres;
104 int state;
105
106 (void)arg;
107 while ( 1 )
108 {
109 WaitEventFlag(usbKernelResources.m_callbackEvent, 1u, WEF_OR | WEF_CLEAR, &efres);
110 while ( 1 )
111 {
112 CpuSuspendIntr(&state);
113 req = cbListStart;
114 if ( req )
115 {
116 if ( req->m_next )
117 req->m_next->m_prev = req->m_prev;
118 else
119 cbListEnd = req->m_prev;
120 if ( req->m_prev )
121 req->m_prev->m_next = req->m_next;
122 else
123 cbListStart = req->m_next;
124 }
125 CpuResumeIntr(state);
126 if ( !req )
127 break;
128 bcopy(req, &reqCopy, sizeof(UsbdIoRequest_t));
129 usbdLock();
130 freeIoRequest(req);
131 usbdUnlock();
132 if ( reqCopy.m_userCallbackProc )
133 {
134#if USE_GP_REGISTER
135 SetGP(reqCopy.m_gpSeg);
136#endif
137 if ( reqCopy.m_req.bNumPackets )
138 reqCopy.m_userCallbackProcMultiIsochronous(reqCopy.m_resultCode, &reqCopy.m_req, reqCopy.m_userCallbackArg);
139 else
140 reqCopy.m_userCallbackProcRegular(reqCopy.m_resultCode, reqCopy.m_transferedBytes, reqCopy.m_userCallbackArg);
141#if USE_GP_REGISTER
142 SetGP(_gp);
143#endif
144 }
145 }
146 }
147}
148
149void usbdReboot(int ac)
150{
151 if ( (unsigned int)ac < 2 )
152 usbdRebootInner();
153}
154
155static void ParseOptionInput(const UsbdArgOption_t *option, const char *arguments)
156{
157 int value_1;
158 const char *p_1;
159 int value_2;
160 const char *p_2;
161
162 value_1 = 0;
163 for ( p_1 = arguments; *p_1 && *p_1 != ','; p_1 += 1 )
164 {
165 if ( (unsigned int)(*p_1 - '0') >= 9 )
166 return;
167 value_1 = 10 * value_1 + (*p_1 - '0');
168 }
169 if ( option->value2 ? (*p_1 != ',') : (*p_1 == ',') )
170 return;
171 if ( arguments < p_1 )
172 *option->value = value_1;
173 if ( !option->value2 )
174 {
175 return;
176 }
177 value_2 = 0;
178 for ( p_2 = p_1 + 1; *p_2; p_2 += 1 )
179 {
180 if ( (unsigned int)(*p_2 - '0') >= 9 )
181 return;
182 value_2 = 10 * value_2 + (*p_2 - '0');
183 }
184 if ( p_1 + 1 < p_2 )
185 *option->value2 = value_2;
186}
187
188int _start(int ac, char *av[], void *startaddr, ModuleInfo_t *mi)
189{
190 int i;
191 UsbdArgOption_t *args_ptr;
192 const char *pParam;
193 char *pArgs;
194 iop_event_t ef;
195 iop_thread_t thparam;
196 iop_sema_t sema;
197 int intrstate;
198
199 (void)startaddr;
200 if ( ac < 0 )
201 return usbdModuleUnload();
202 for ( i = 1; i < ac; i += 1 )
203 {
204 for ( args_ptr = SupportedArgs; args_ptr->param; args_ptr += 1 )
205 {
206 int j;
207 for ( j = 0, pParam = args_ptr->param, pArgs = av[i]; pParam[j] && pParam[j] == pArgs[j]; j += 1 )
208 {
209 }
210 if ( !pParam[j] )
211 {
212 ParseOptionInput(args_ptr, pArgs);
213 break;
214 }
215 }
216 }
217 dbg_printf("Intr handler...\n");
218 DisableIntr(IOP_IRQ_USB, &intrstate);
219 if ( RegisterIntrHandler(IOP_IRQ_USB, 1, usbdIntrHandler, &usbKernelResources) )
220 {
221 if ( intrstate == IOP_IRQ_USB )
222 {
223 EnableIntr(IOP_IRQ_USB);
224 return MODULE_NO_RESIDENT_END;
225 }
226 }
227 else
228 {
229 dbg_printf("library entries...\n");
230 if ( !RegisterLibraryEntries(&_exp_usbd) )
231 {
232 dbg_printf("Threads and events...\n");
233
234 sema.attr = SA_THPRI;
235 sema.initial = 1;
236 sema.max = 1;
237 sema.option = 0;
238 usbKernelResources.m_usbdSema = CreateSema(&sema);
239 if ( usbKernelResources.m_usbdSema >= 0 )
240 {
241 ef.attr = EA_SINGLE;
242 ef.option = 0;
243 ef.bits = 0;
244 usbKernelResources.m_hcdIrqEvent = CreateEventFlag(&ef);
245 if ( usbKernelResources.m_hcdIrqEvent >= 0 )
246 {
247 dbg_printf("HCD thread...\n");
248 thparam.attr = TH_C;
249 thparam.thread = hcdIrqThread;
250#ifndef MINI_DRIVER
251 thparam.stacksize = 0x4000; // 16KiB
252#else
253 thparam.stacksize = 0x0800; // 2KiB
254#endif
255 thparam.option = 0;
256 thparam.priority = usbConfig.m_hcdThreadPrio;
257 usbKernelResources.m_hcdTid = CreateThread(&thparam);
258 if ( usbKernelResources.m_hcdTid >= 0 && !StartThread(usbKernelResources.m_hcdTid, NULL) )
259 {
260 ef.attr = EA_SINGLE;
261 ef.option = 0;
262 ef.bits = 0;
263 usbKernelResources.m_callbackEvent = CreateEventFlag(&ef);
264 if ( usbKernelResources.m_callbackEvent >= 0 )
265 {
266 dbg_printf("Callback thread...\n");
267 thparam.attr = TH_C;
268 thparam.thread = callbackThreadFunc;
269#ifndef MINI_DRIVER
270 thparam.stacksize = 0x4000; // 16KiB
271#else
272 thparam.stacksize = 0x0800; // 2KiB
273#endif
274 thparam.option = 0;
275 thparam.priority = usbConfig.m_cbThreadPrio;
276 usbKernelResources.m_callbackTid = CreateThread(&thparam);
277 if (
278 usbKernelResources.m_callbackTid >= 0 && !StartThread(usbKernelResources.m_callbackTid, NULL)
279 && usbdInitInner() >= 0 )
280 {
281 dbg_printf("Enabling interrupts...\n");
282 EnableIntr(IOP_IRQ_USB);
283 dbg_printf("Init done\n");
284#if 0
285 return MODULE_REMOVABLE_END;
286#else
287 if ( mi && ((mi->newflags & 2) != 0) )
288 mi->newflags |= 0x10;
289 return MODULE_RESIDENT_END;
290#endif
291 }
292 }
293 }
294 }
295 }
296 }
297 else
298 {
299 dbg_printf("RegisterLibraryEntries failed\n");
300 }
301 if ( usbKernelResources.m_callbackTid > 0 )
302 DeleteThread(usbKernelResources.m_callbackTid);
303 if ( usbKernelResources.m_callbackEvent > 0 )
304 DeleteEventFlag(usbKernelResources.m_callbackEvent);
305 if ( usbKernelResources.m_hcdTid > 0 )
306 DeleteThread(usbKernelResources.m_hcdTid);
307 if ( usbKernelResources.m_hcdIrqEvent > 0 )
308 DeleteEventFlag(usbKernelResources.m_hcdIrqEvent);
309 if ( usbKernelResources.m_usbdSema > 0 )
310 DeleteSema(usbKernelResources.m_usbdSema);
311 ReleaseIntrHandler(IOP_IRQ_USB);
312 }
313 return MODULE_NO_RESIDENT_END;
314}
315
316static int usbdModuleUnload(void)
317{
318 int intrstate;
319
320 if ( ReleaseLibraryEntries(&_exp_usbd) == 0 )
321 {
322 return MODULE_REMOVABLE_END;
323 }
324 DisableIntr(IOP_IRQ_USB, &intrstate);
325 ReleaseIntrHandler(IOP_IRQ_USB);
326 TerminateThread(usbKernelResources.m_hcdTid);
327 TerminateThread(usbKernelResources.m_callbackTid);
328 DeleteThread(usbKernelResources.m_hcdTid);
329 DeleteThread(usbKernelResources.m_callbackTid);
330 DeleteEventFlag(usbKernelResources.m_hcdIrqEvent);
331 DeleteEventFlag(usbKernelResources.m_callbackEvent);
332 DeleteSema(usbKernelResources.m_usbdSema);
333 deinitHcd();
334 deinitHubDriver();
335 return MODULE_NO_RESIDENT_END;
336}
int CpuResumeIntr(int state)
Definition intrman.c:227
int RegisterIntrHandler(int irq, int mode, int(*handler)(void *), void *arg)
Definition intrman.c:125
int ReleaseIntrHandler(int irq)
Definition intrman.c:167
int DisableIntr(int irq, int *res)
Definition intrman.c:395
int CpuSuspendIntr(int *state)
Definition intrman.c:205
int EnableIntr(int irq)
Definition intrman.c:346
u16 newflags
Definition loadcore.h:36
#define EA_SINGLE
Definition thevent.h:33