ps2sdk  1.1
A collection of Open Source libraries used for developing applications on Sony's PlayStation 2® (PS2).
audsrv_rpc.c
Go to the documentation of this file.
1 /*
2 # _____ ___ ____ ___ ____
3 # ____| | ____| | | |____|
4 # | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
5 #-----------------------------------------------------------------------
6 # Copyright 2005, ps2dev - http://www.ps2dev.org
7 # Licenced under GNU Library General Public License version 2
8 # Review ps2sdk README & LICENSE files for further details.
9 */
10 
16 #include <stdio.h>
17 #include <kernel.h>
18 #include <sifrpc.h>
19 #include <tamtypes.h>
20 #include <string.h>
21 #include <iopheap.h>
22 
23 #include <audsrv.h>
24 #include "audsrv_rpc.h"
25 
26 #define MIN(a,b) ((a) <= (b)) ? (a) : (b)
27 
28 /* rpc mambo jambo */
29 static struct t_SifRpcClientData cd0;
30 static unsigned int sbuff[4096] __attribute__((aligned (64)));
31 static struct t_SifRpcDataQueue cb_queue;
32 static struct t_SifRpcServerData cb_srv;
33 static unsigned char rpc_server_stack[0x1800] __attribute__((aligned (16)));
34 
35 extern void *_gp;
36 
37 static int initialized = 0;
40 static int completion_sema;
41 
43 static void *on_cdda_stop_arg = NULL;
44 
46 static void *on_fillbuf_arg = NULL;
47 
48 static const unsigned short vol_values[26] =
49 {
50  0x0000,
51  0x0000, 0x0096, 0x0190, 0x0230, 0x0320,
52  0x042E, 0x0532, 0x05FA, 0x06C2, 0x088E,
53  0x09F6, 0x0BC2, 0x0DC0, 0x0FF0, 0x118A,
54  0x1482, 0x1752, 0x1B4E, 0x1F40, 0x2378,
55  0x28D2, 0x2EFE, 0x34F8, 0x3A5C, 0x3FFF
56 };
57 
61 static void set_error(int err)
62 {
63  audsrv_error = err;
64 }
65 
67 {
68  return audsrv_error;
69 }
70 
76 static int call_rpc_1(int func, int arg)
77 {
78  int ret;
79 
81 
82  sbuff[0] = arg;
83  SifCallRpc(&cd0, func, 0, sbuff, 1*4, sbuff, 4, NULL, NULL);
84 
85  ret = sbuff[0];
87 
88  set_error(ret);
89 
90  return ret;
91 }
92 
99 static int call_rpc_2(int func, int arg1, int arg2)
100 {
101  int ret;
102 
104 
105  sbuff[0] = arg1;
106  sbuff[1] = arg2;
107  SifCallRpc(&cd0, func, 0, sbuff, 2*4, sbuff, 4, NULL, NULL);
108 
109  ret = sbuff[0];
111 
112  set_error(ret);
113 
114  return ret;
115 }
116 
118 {
120 
121  SifCallRpc(&cd0, AUDSRV_QUIT, 0, sbuff, 1*4, sbuff, 4, NULL, NULL);
123 
128 
130  return 0;
131 }
132 
134 {
135  int ret;
136 
138 
139  sbuff[0] = fmt->freq;
140  sbuff[1] = fmt->bits;
141  sbuff[2] = fmt->channels;
142  SifCallRpc(&cd0, AUDSRV_SET_FORMAT, 0, sbuff, 3*4, sbuff, 4, NULL, NULL);
143 
144  ret = sbuff[0];
146 
147  set_error(ret);
148 
149  return ret;
150 }
151 
152 int audsrv_wait_audio(int bytes)
153 {
154  return call_rpc_1(AUDSRV_WAIT_AUDIO, bytes);
155 }
156 
157 int audsrv_set_volume(int volume)
158 {
159  if (volume > MAX_VOLUME)
160  {
161  volume = MAX_VOLUME;
162  }
163  else if (volume < MIN_VOLUME)
164  {
165  volume = MIN_VOLUME;
166  }
167 
168  return call_rpc_1(AUDSRV_SET_VOLUME, vol_values[volume/4]);
169 }
170 
171 int audsrv_play_cd(int track)
172 {
173  return call_rpc_1(AUDSRV_PLAY_CD, track);
174 }
175 
176 int audsrv_play_sectors(int start, int end)
177 {
178  return call_rpc_2(AUDSRV_PLAY_SECTORS, start, end);
179 }
180 
182 {
183  int ret;
184  ret = call_rpc_1(AUDSRV_STOP_CD, 0);
185  return ret;
186 }
187 
189 {
190  return call_rpc_1(AUDSRV_GET_CDPOS, 0);
191 }
192 
194 {
195  return call_rpc_1(AUDSRV_GET_TRACKPOS, 0);
196 }
197 
199 {
200  return call_rpc_1(AUDSRV_GET_NUMTRACKS, 0);
201 }
202 
204 {
205  return call_rpc_1(AUDSRV_GET_TRACKOFFSET, track);
206 }
207 
209 {
210  return call_rpc_1(AUDSRV_PAUSE_CD, 0);
211 }
212 
214 {
215  return call_rpc_1(AUDSRV_RESUME_CD, 0);
216 }
217 
219 {
220  return call_rpc_1(AUDSRV_GET_CD_TYPE, 0);
221 }
222 
224 {
225  return call_rpc_1(AUDSRV_GET_CD_STATUS, 0);
226 }
227 
228 int audsrv_play_audio(const char *chunk, int bytes)
229 {
230  int copy, maxcopy, copied;
231  int packet_size;
232  int sent = 0;
233 
235  maxcopy = sizeof(sbuff) - sizeof(int);
236  while (bytes > 0)
237  {
239 
240  copy = MIN(bytes, maxcopy);
241  sbuff[0] = copy;
242  memcpy(&sbuff[1], chunk, copy);
243  packet_size = copy + sizeof(int);
244  SifCallRpc(&cd0, AUDSRV_PLAY_AUDIO, 0, sbuff, packet_size, sbuff, 1*4, NULL, NULL);
245 
246  copied = sbuff[0];
248 
249  if (copied < 0)
250  {
251  /* there was an error */
252  set_error(-copied);
253  break;
254  }
255 
256  chunk = chunk + copy;
257  bytes = bytes - copy;
258  sent = sent + copied;
259  }
260 
261  return sent;
262 }
263 
265 {
266  int ret;
267  ret = call_rpc_1(AUDSRV_STOP_AUDIO, 0);
268  return ret;
269 }
270 
271 static void *audsrv_ee_rpc_handler(int fnum, void *buffer, int len)
272 {
273  switch(fnum){
275  if (on_fillbuf != NULL)
277  break;
279  if (on_cdda_stop != NULL)
281  break;
282  }
283 
284  return buffer;
285 }
286 
287 static void rpc_server_thread(void *arg)
288 {
289  static unsigned char cb_rpc_buffer[64] __attribute__((aligned(64)));
290 
294 }
295 
297 {
299  ee_thread_t rpcThread;
300  int ret;
301 
302  if (initialized)
303  {
304  /* already done */
305  return 0;
306  }
307 
308  memset(&cd0, '\0', sizeof(cd0));
309 
310  while (1)
311  {
312  if (SifBindRpc(&cd0, AUDSRV_IRX, 0) < 0)
313  {
315  return -1;
316  }
317 
318  if (cd0.server != 0)
319  {
320  break;
321  }
322 
323  nopdelay();
324  }
325 
326  compSema.init_count = 1;
327  compSema.max_count = 1;
328  compSema.option = 0;
330  if (completion_sema < 0)
331  {
333  return -1;
334  }
335 
336  /* Create RPC server */
337  rpcThread.attr = 0;
338  rpcThread.option = 0;
339  rpcThread.func = &rpc_server_thread;
340  rpcThread.stack = rpc_server_stack;
341  rpcThread.stack_size = sizeof(rpc_server_stack);
342  rpcThread.gp_reg = &_gp;
343  rpcThread.initial_priority = 0x60;
344  rpc_server_thread_id = CreateThread(&rpcThread);
346 
347  SifCallRpc(&cd0, AUDSRV_INIT, 0, sbuff, 64, sbuff, 64, NULL, NULL);
348  ret = sbuff[0];
349  if (ret != 0)
350  {
351  set_error(ret);
352  return ret;
353  }
354 
355  /* initialize IOP heap (for adpcm samples) */
356  SifInitIopHeap();
357 
359  return AUDSRV_ERR_NOERROR;
360 }
361 
363 {
364  return call_rpc_1(AUDSRV_INIT_ADPCM, 0);
365 }
366 
367 int audsrv_adpcm_set_volume(int ch, int volume)
368 {
369  if (volume > MAX_VOLUME)
370  {
371  volume = MAX_VOLUME;
372  }
373  else if (volume < MIN_VOLUME)
374  {
375  volume = MIN_VOLUME;
376  }
377 
378  return call_rpc_2(AUDSRV_ADPCM_SET_VOLUME, ch, vol_values[volume/4]);
379 }
380 
381 int audsrv_load_adpcm(audsrv_adpcm_t *adpcm, void *buffer, int size)
382 {
383  void* iop_addr;
384  SifDmaTransfer_t sifdma;
385  int id, ret;
386 
387  iop_addr = SifAllocIopHeap(size);
388  if (iop_addr == 0)
389  {
390  return -AUDSRV_ERR_OUT_OF_MEMORY;
391  }
392 
393  sifdma.src = buffer;
394  sifdma.dest = iop_addr;
395  sifdma.size = size;
396  sifdma.attr = 0;
397 
398  /* send by dma */
399  while((id = SifSetDma(&sifdma, 1)) == 0);
400  while(SifDmaStat(id) >= 0);
401 
403 
404  sbuff[0] = (int)iop_addr;
405  sbuff[1] = size;
406  sbuff[2] = (int)adpcm; /* use as id */
407 
408  SifCallRpc(&cd0, AUDSRV_LOAD_ADPCM, 0, sbuff, 12, sbuff, 16, NULL, NULL);
409 
410  if(sbuff[0] != 0)
411  {
412  adpcm->buffer = 0;
413  ret = sbuff[0];
414  }
415  else
416  {
417  adpcm->buffer = buffer;
418  adpcm->size = size;
419  adpcm->pitch = sbuff[1];
420  adpcm->loop = sbuff[2];
421  adpcm->channels = sbuff[3];
422  ret = AUDSRV_ERR_NOERROR;
423  }
424 
426 
427  SifFreeIopHeap(iop_addr);
428 
429  return ret;
430 }
431 
433 {
434  /* on iop side, the sample id is like the pointer on ee side */
435  return call_rpc_2(AUDSRV_PLAY_ADPCM, ch, (u32)adpcm);
436 }
437 
439 {
440  switch(audsrv_get_error())
441  {
442  case AUDSRV_ERR_NOERROR:
443  return "No error";
444 
446  return "Not initialized";
447 
449  return "Out of IOP memory";
450 
452  return "RPC operation failed";
453 
455  return "Format not supported";
456 
457  case AUDSRV_ERR_NO_DISC:
458  return "No disc in drive";
459  }
460 
461  return "Unknown error";
462 }
463 
465 {
466  on_cdda_stop = cb;
467  on_cdda_stop_arg = arg;
468  return AUDSRV_ERR_NOERROR;
469 }
470 
471 int audsrv_on_fillbuf(int amount, audsrv_callback_t cb, void *arg)
472 {
473  int err;
474 
475  on_fillbuf = 0;
476  on_fillbuf_arg = 0;
477 
478  err = call_rpc_1(AUDSRV_SET_THRESHOLD, amount);
479  if (err != 0)
480  {
481  return err;
482  }
483 
484  on_fillbuf = cb;
485  on_fillbuf_arg = arg;
486  return AUDSRV_ERR_NOERROR;
487 }
#define AUDSRV_ERR_FORMAT_NOT_SUPPORTED
Definition: audsrv.h:31
#define AUDSRV_ERR_OUT_OF_MEMORY
Definition: audsrv.h:32
#define AUDSRV_ERR_NOT_INITIALIZED
Definition: audsrv.h:29
#define AUDSRV_ERR_FAILED_TO_CREATE_SEMA
Definition: audsrv.h:38
#define AUDSRV_ERR_NOERROR
Definition: audsrv.h:28
#define MAX_VOLUME
Definition: audsrv.h:25
#define AUDSRV_ERR_RPC_FAILED
Definition: audsrv.h:30
#define AUDSRV_ERR_NO_DISC
Definition: audsrv.h:34
#define MIN_VOLUME
Definition: audsrv.h:22
int(* audsrv_callback_t)(void *arg)
Definition: audsrv.h:65
#define AUDSRV_IRX
Definition: audsrv.h:19
int audsrv_play_sectors(int start, int end)
Definition: audsrv_rpc.c:176
static struct t_SifRpcClientData cd0
Definition: audsrv_rpc.c:29
int audsrv_get_numtracks()
Definition: audsrv_rpc.c:198
static int call_rpc_2(int func, int arg1, int arg2)
Definition: audsrv_rpc.c:99
static void * on_cdda_stop_arg
Definition: audsrv_rpc.c:43
static void rpc_server_thread(void *arg)
Definition: audsrv_rpc.c:287
static void * on_fillbuf_arg
Definition: audsrv_rpc.c:46
const char * audsrv_get_error_string()
Definition: audsrv_rpc.c:438
int audsrv_adpcm_set_volume(int ch, int volume)
Definition: audsrv_rpc.c:367
int audsrv_get_error()
Definition: audsrv_rpc.c:66
int audsrv_resume_cd()
Definition: audsrv_rpc.c:213
int audsrv_init()
Definition: audsrv_rpc.c:296
#define MIN(a, b)
Definition: audsrv_rpc.c:26
int audsrv_pause_cd()
Definition: audsrv_rpc.c:208
static void * audsrv_ee_rpc_handler(int fnum, void *buffer, int len)
Definition: audsrv_rpc.c:271
static audsrv_callback_t on_fillbuf
Definition: audsrv_rpc.c:45
static int call_rpc_1(int func, int arg)
Definition: audsrv_rpc.c:76
int audsrv_get_cd_type()
Definition: audsrv_rpc.c:218
static int completion_sema
Definition: audsrv_rpc.c:40
int audsrv_play_audio(const char *chunk, int bytes)
Definition: audsrv_rpc.c:228
int audsrv_on_cdda_stop(audsrv_callback_t cb, void *arg)
Definition: audsrv_rpc.c:464
int audsrv_adpcm_init()
Definition: audsrv_rpc.c:362
int audsrv_stop_audio()
Definition: audsrv_rpc.c:264
static unsigned char rpc_server_stack[0x1800]
Definition: audsrv_rpc.c:33
int audsrv_ch_play_adpcm(int ch, audsrv_adpcm_t *adpcm)
Definition: audsrv_rpc.c:432
int audsrv_play_cd(int track)
Definition: audsrv_rpc.c:171
static int rpc_server_thread_id
Definition: audsrv_rpc.c:38
int audsrv_get_trackpos()
Definition: audsrv_rpc.c:193
static int audsrv_error
Definition: audsrv_rpc.c:39
int audsrv_load_adpcm(audsrv_adpcm_t *adpcm, void *buffer, int size)
Definition: audsrv_rpc.c:381
static audsrv_callback_t on_cdda_stop
Definition: audsrv_rpc.c:42
static struct t_SifRpcServerData cb_srv
Definition: audsrv_rpc.c:32
void * _gp
static struct t_SifRpcDataQueue cb_queue
Definition: audsrv_rpc.c:31
int audsrv_set_volume(int volume)
Definition: audsrv_rpc.c:157
int audsrv_get_cdpos()
Definition: audsrv_rpc.c:188
static unsigned int sbuff[4096]
Definition: audsrv_rpc.c:30
int audsrv_stop_cd()
Definition: audsrv_rpc.c:181
static int initialized
Definition: audsrv_rpc.c:37
int audsrv_on_fillbuf(int amount, audsrv_callback_t cb, void *arg)
Definition: audsrv_rpc.c:471
int audsrv_wait_audio(int bytes)
Definition: audsrv_rpc.c:152
static const unsigned short vol_values[26]
Definition: audsrv_rpc.c:48
static void set_error(int err)
Definition: audsrv_rpc.c:61
int audsrv_get_track_offset(int track)
Definition: audsrv_rpc.c:203
int audsrv_set_format(struct audsrv_fmt_t *fmt)
Definition: audsrv_rpc.c:133
int audsrv_get_cd_status()
Definition: audsrv_rpc.c:223
int audsrv_quit()
Definition: audsrv_rpc.c:117
#define AUDSRV_WAIT_AUDIO
Definition: audsrv_rpc.h:31
#define AUDSRV_PAUSE_CD
Definition: audsrv_rpc.h:43
#define AUDSRV_SET_FORMAT
Definition: audsrv_rpc.h:29
#define AUDSRV_SET_THRESHOLD
Definition: audsrv_rpc.h:34
#define AUDSRV_STOP_AUDIO
Definition: audsrv_rpc.h:32
#define AUDSRV_GET_NUMTRACKS
Definition: audsrv_rpc.h:41
#define AUDSRV_GET_CD_STATUS
Definition: audsrv_rpc.h:46
#define AUDSRV_QUIT
Definition: audsrv_rpc.h:25
#define AUDSRV_GET_TRACKPOS
Definition: audsrv_rpc.h:40
#define AUDSRV_PLAY_ADPCM
Definition: audsrv_rpc.h:52
#define AUDSRV_GET_CDPOS
Definition: audsrv_rpc.h:39
#define AUDSRV_LOAD_ADPCM
Definition: audsrv_rpc.h:51
#define AUDSRV_GET_CD_TYPE
Definition: audsrv_rpc.h:47
#define AUDSRV_ADPCM_SET_VOLUME
Definition: audsrv_rpc.h:53
#define AUDSRV_RESUME_CD
Definition: audsrv_rpc.h:44
#define AUDSRV_CDDA_CALLBACK
Definition: audsrv_rpc.h:56
#define AUDSRV_PLAY_SECTORS
Definition: audsrv_rpc.h:45
#define AUDSRV_SET_VOLUME
Definition: audsrv_rpc.h:33
#define AUDSRV_INIT_ADPCM
Definition: audsrv_rpc.h:50
#define AUDSRV_PLAY_CD
Definition: audsrv_rpc.h:37
#define AUDSRV_STOP_CD
Definition: audsrv_rpc.h:38
#define AUDSRV_FILLBUF_CALLBACK
Definition: audsrv_rpc.h:55
#define AUDSRV_GET_TRACKOFFSET
Definition: audsrv_rpc.h:42
#define AUDSRV_INIT
Definition: audsrv_rpc.h:24
#define AUDSRV_PLAY_AUDIO
Definition: audsrv_rpc.h:30
void * SifAllocIopHeap(int size)
int SifFreeIopHeap(void *addr)
int SifInitIopHeap(void)
s32 CreateSema(ee_sema_t *sema)
s32 SignalSema(s32 sema_id)
s32 DeleteSema(s32 sema_id)
u32 SifSetDma(SifDmaTransfer_t *sdd, s32 len)
static void nopdelay(void)
Definition: kernel.h:141
s32 CreateThread(ee_thread_t *thread)
s32 WaitSema(s32 sema_id)
s32 StartThread(s32 thread_id, void *args)
s32 SifDmaStat(u32 id)
s32 TerminateThread(s32 thread_id)
s32 DeleteThread(s32 thread_id)
s32 GetThreadId(void)
ee_sema_t compSema
Definition: ps2cam_rpc.c:30
u8 buffer[128]
Definition: rpc_client.c:19
SifRpcServerData_t * SifRegisterRpc(SifRpcServerData_t *srv, int sid, SifRpcFunc_t func, void *buff, SifRpcFunc_t cfunc, void *cbuff, SifRpcDataQueue_t *qd)
SifRpcDataQueue_t * SifSetRpcQueue(SifRpcDataQueue_t *q, int thread_id)
SifRpcServerData_t * SifRemoveRpc(SifRpcServerData_t *sd, SifRpcDataQueue_t *queue)
void SifRpcLoop(SifRpcDataQueue_t *q)
SifRpcDataQueue_t * SifRemoveRpcQueue(SifRpcDataQueue_t *qd)
int SifBindRpc(SifRpcClientData_t *client, int rpc_number, int mode)
int SifCallRpc(SifRpcClientData_t *client, int rpc_number, int mode, void *send, int ssize, void *receive, int rsize, SifRpcEndFunc_t end_function, void *end_param)
void * dest
Definition: sifdma.h:55
void * src
Definition: sifdma.h:54
void * buffer
Definition: audsrv.h:57
int channels
Definition: audsrv.h:56
int bits
Definition: audsrv.h:46
int freq
Definition: audsrv.h:44
int channels
Definition: audsrv.h:48
int init_count
Definition: kernel.h:218
int max_count
Definition: kernel.h:217
u32 option
Definition: kernel.h:221
void * gp_reg
Definition: kernel.h:230
u32 option
Definition: kernel.h:234
int stack_size
Definition: kernel.h:229
void * func
Definition: kernel.h:227
void * stack
Definition: kernel.h:228
u32 attr
Definition: kernel.h:233
int initial_priority
Definition: kernel.h:231
#define NULL
Definition: tamtypes.h:91
unsigned int u32
Definition: tamtypes.h:30