Fix libogc hardware lighting (GX_SetChanCtrl) - patch from https://sourceforge.net...
[libogc.git] / libdb / geckousb.c
blob2e92e2dd79f94e77ab97f19c5177296f922c970d
1 #include <stdlib.h>
2 #include <string.h>
3 #include <stdio.h>
4 #include <errno.h>
5 #include <signal.h>
6 #include <gccore.h>
8 #include "geckousb.h"
10 #define _SHIFTL(v, s, w) \
11 ((u32) (((u32)(v) & ((0x01 << (w)) - 1)) << (s)))
12 #define _SHIFTR(v, s, w) \
13 ((u32)(((u32)(v) >> (s)) & ((0x01 << (w)) - 1)))
15 static struct dbginterface usb_device;
17 static __inline__ int __send_command(s32 chn,u16 *cmd)
19 s32 ret;
21 ret = 0;
22 if(!EXI_Select(chn,EXI_DEVICE_0,EXI_SPEED32MHZ)) ret |= 0x01;
23 if(!EXI_Imm(chn,cmd,sizeof(u16),EXI_READWRITE,NULL)) ret |= 0x02;
24 if(!EXI_Sync(chn)) ret |= 0x04;
25 if(!EXI_Deselect(chn)) ret |= 0x08;
27 if(ret) return 0;
28 return 1;
31 static int __usb_sendbyte(s32 chn,char ch)
33 s32 ret;
34 u16 val;
36 val = (0xB000|_SHIFTL(ch,4,8));
37 ret = __send_command(chn,&val);
38 if(ret==1 && !(val&0x0400)) ret = 0;
40 return ret;
43 static int __usb_recvbyte(s32 chn,char *ch)
45 s32 ret;
46 u16 val;
48 *ch = 0;
49 val = 0xA000;
50 ret = __send_command(chn,&val);
51 if(ret==1 && !(val&0x0800)) ret = 0;
52 else if(ret==1) *ch = (val&0xff);
54 return ret;
57 static int __usb_checksend(s32 chn)
59 s32 ret;
60 u16 val;
62 val = 0xC000;
63 ret = __send_command(chn,&val);
64 if(ret==1 && !(val&0x0400)) ret = 0;
66 return ret;
69 static int __usb_checkrecv(s32 chn)
71 s32 ret;
72 u16 val;
74 val = 0xD000;
75 ret = __send_command(chn,&val);
76 if(ret==1 && !(val&0x0400)) ret = 0;
78 return ret;
81 static void __usb_flush(s32 chn)
83 char tmp;
85 if(!EXI_Lock(chn,EXI_DEVICE_0,NULL)) return;
87 while(__usb_recvbyte(chn,&tmp));
89 EXI_Unlock(chn);
93 static int __usb_isgeckoalive(s32 chn)
95 s32 ret;
96 u16 val;
98 if(!EXI_Lock(chn,EXI_DEVICE_0,NULL)) return 0;
100 val = 0x9000;
101 ret = __send_command(chn,&val);
102 if(ret==1 && !(val&0x0470)) ret = 0;
104 EXI_Unlock(chn);
105 return ret;
108 static int __usb_recvbuffer(s32 chn,void *buffer,int size)
110 s32 ret;
111 s32 left = size;
112 char *ptr = (char*)buffer;
114 if(!EXI_Lock(chn,EXI_DEVICE_0,NULL)) return 0;
116 while(left>0) {
117 if(__usb_checkrecv(chn)) {
118 ret = __usb_recvbyte(chn,ptr);
119 if(ret==0) break;
121 ptr++;
122 left--;
126 EXI_Unlock(chn);
127 return (size - left);
130 static int __usb_sendbuffer(s32 chn,const void *buffer,int size)
132 s32 ret;
133 s32 left = size;
134 char *ptr = (char*)buffer;
136 if(!EXI_Lock(chn,EXI_DEVICE_0,NULL)) return 0;
138 while(left>0) {
139 if(__usb_checksend(chn)) {
140 ret = __usb_sendbyte(chn,*ptr);
141 if(ret==0) break;
143 ptr++;
144 left--;
148 EXI_Unlock(chn);
149 return (size - left);
152 static int usbopen(struct dbginterface *device)
154 if(!__usb_isgeckoalive(device->fhndl)) {
155 return -1;
158 return 0;
161 static int usbclose(struct dbginterface *device)
163 return 0;
166 static int usbwait(struct dbginterface *device)
168 return 0;
171 static int usbread(struct dbginterface *device,void *buffer,int size)
173 int ret;
174 ret = __usb_recvbuffer(device->fhndl,buffer,size);
175 return ret;
178 static int usbwrite(struct dbginterface *device,const void *buffer,int size)
180 int ret;
181 ret = __usb_sendbuffer(device->fhndl,buffer,size);
182 return ret;
185 struct dbginterface* usb_init(s32 channel)
187 usb_device.fhndl = channel;
188 if(__usb_isgeckoalive(channel))
189 __usb_flush(channel);
191 usb_device.open = usbopen;
192 usb_device.close = usbclose;
193 usb_device.wait = usbwait;
194 usb_device.read = usbread;
195 usb_device.write = usbwrite;
197 return &usb_device;