SMB directory recursion works now, fixed an ugly bug in smb_recv
[libogc.git] / libogc / usbgecko.c
blob0b7c7250696bcdfeda02eab6e2fabc08100f1118
1 #include <stdlib.h>
2 #include <string.h>
3 #include <stdio.h>
4 #include <errno.h>
5 #include <signal.h>
6 #include <gccore.h>
7 #include <machine/processor.h>
9 #include "usbgecko.h"
11 #define _SHIFTL(v, s, w) \
12 ((u32) (((u32)(v) & ((0x01 << (w)) - 1)) << (s)))
13 #define _SHIFTR(v, s, w) \
14 ((u32)(((u32)(v) >> (s)) & ((0x01 << (w)) - 1)))
17 static u32 usbgecko_inited = 0;
18 static lwpq_t wait_exi_queue[2];
20 static s32 __usbgecko_exi_unlock(s32 chan,s32 dev)
22 LWP_ThreadBroadcast(wait_exi_queue[chan]);
23 return 1;
26 static void __usbgecko_init()
28 u32 i;
30 for(i=0;i<EXI_CHANNEL_2;i++) {
31 LWP_InitQueue(&wait_exi_queue[i]);
33 usbgecko_inited = 1;
36 static __inline__ void __usbgecko_exi_wait(s32 chn)
38 u32 level;
40 _CPU_ISR_Disable(level);
41 if(!usbgecko_inited) __usbgecko_init();
42 while(EXI_Lock(chn,EXI_DEVICE_0,__usbgecko_exi_unlock)==0) {
43 LWP_ThreadSleep(wait_exi_queue[chn]);
45 _CPU_ISR_Restore(level);
48 static __inline__ int __send_command(s32 chn,u16 *cmd)
50 s32 ret = 0;
52 if(!EXI_Select(chn,EXI_DEVICE_0,EXI_SPEED32MHZ)) ret |= 0x01;
53 if(!EXI_Imm(chn,cmd,sizeof(u16),EXI_READWRITE,NULL)) ret |= 0x02;
54 if(!EXI_Sync(chn)) ret |= 0x04;
55 if(!EXI_Deselect(chn)) ret |= 0x08;
57 if(ret) return 0;
58 return 1;
61 static int __usb_sendbyte(s32 chn,char ch)
63 s32 ret;
64 u16 val;
66 val = (0xB000|_SHIFTL(ch,4,8));
67 ret = __send_command(chn,&val);
68 if(ret==1 && !(val&0x0400)) ret = 0;
70 return ret;
73 static int __usb_recvbyte(s32 chn,char *ch)
75 s32 ret;
76 u16 val;
78 *ch = 0;
79 val = 0xA000;
80 ret = __send_command(chn,&val);
81 if(ret==1 && !(val&0x0800)) ret = 0;
82 else if(ret==1) *ch = (val&0xff);
84 return ret;
87 int __usb_checksend(s32 chn)
89 s32 ret;
90 u16 val;
92 val = 0xC000;
93 ret = __send_command(chn,&val);
94 if(ret==1 && !(val&0x0400)) ret = 0;
96 return ret;
99 int __usb_checkrecv(s32 chn)
101 s32 ret;
102 u16 val;
104 val = 0xD000;
105 ret = __send_command(chn,&val);
106 if(ret==1 && !(val&0x0400)) ret = 0;
108 return ret;
111 void usb_flush(s32 chn)
113 char tmp;
115 __usbgecko_exi_wait(chn);
116 while(__usb_recvbyte(chn,&tmp));
117 EXI_Unlock(chn);
120 int usb_isgeckoalive(s32 chn)
122 s32 ret;
123 u16 val;
124 u32 id = 0;
126 if(EXI_GetID(chn,EXI_DEVICE_0,&id)==0) return 0;
127 if(id!=0) return 0;
129 __usbgecko_exi_wait(chn);
131 val = 0x9000;
132 ret = __send_command(chn,&val);
133 if(ret==1 && !(val&0x0470)) ret = 0;
135 EXI_Unlock(chn);
137 return ret;
140 int usb_recvbuffer(s32 chn,void *buffer,int size)
142 s32 ret;
143 s32 left = size;
144 char *ptr = (char*)buffer;
146 __usbgecko_exi_wait(chn);
147 while(left>0) {
148 ret = __usb_recvbyte(chn,ptr);
149 if(ret==0) break;
151 ptr++;
152 left--;
154 EXI_Unlock(chn);
156 return (size - left);
159 int usb_sendbuffer(s32 chn,const void *buffer,int size)
161 s32 ret;
162 s32 left = size;
163 char *ptr = (char*)buffer;
165 __usbgecko_exi_wait(chn);
166 while(left>0) {
167 ret = __usb_sendbyte(chn,*ptr);
168 if(ret==0) break;
170 ptr++;
171 left--;
173 EXI_Unlock(chn);
175 return (size - left);
178 int usb_recvbuffer_safe(s32 chn,void *buffer,int size)
180 s32 ret;
181 s32 left = size;
182 char *ptr = (char*)buffer;
184 __usbgecko_exi_wait(chn);
185 while(left>0) {
186 if(__usb_checkrecv(chn)) {
187 ret = __usb_recvbyte(chn,ptr);
188 if(ret==0) break;
190 ptr++;
191 left--;
194 EXI_Unlock(chn);
196 return (size - left);
199 int usb_sendbuffer_safe(s32 chn,const void *buffer,int size)
201 s32 ret;
202 s32 left = size;
203 char *ptr = (char*)buffer;
205 __usbgecko_exi_wait(chn);
206 while(left>0) {
207 if(__usb_checksend(chn)) {
208 ret = __usb_sendbyte(chn,*ptr);
209 if(ret==0) break;
211 ptr++;
212 left--;
215 EXI_Unlock(chn);
217 return (size - left);