00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "register.h"
00021 #include "util/attributes.h"
00022 #include "util/macro.h"
00023 #include "util/logging.h"
00024 #include "util/mutex.h"
00025
00026 #include <stdlib.h>
00027 #include <string.h>
00028
00029 #define BD_PSR_COUNT 128
00030 #define BD_GPR_COUNT 4096
00031
00032
00033
00034
00035
00036
00037
00038 static const uint32_t bd_psr_init[BD_PSR_COUNT] = {
00039 1,
00040 0xff,
00041 0x0fff0fff,
00042 1,
00043 0xffff,
00044 0xffff,
00045 0,
00046 0,
00047 0,
00048 0,
00049 0xffff,
00050 0,
00051 0xff,
00052 0xff,
00053 0xffff,
00054 0xffff,
00055 0xffffff,
00056 0xffffff,
00057 0xffffff,
00058 0xffff,
00059 0x07,
00060 0,
00061 0,
00062 0,
00063 0,
00064 0,
00065 0,
00066 0,
00067 0,
00068 0x03,
00069 0x1ffff,
00070 0x080200,
00071 0,
00072 0,
00073 0,
00074 0,
00075 0xffff,
00076 0xffff,
00077 0,
00078 0,
00079 0,
00080 0,
00081 0xffff,
00082 0,
00083 0xff,
00084 0,
00085 0,
00086 0,
00087 0xffffffff,
00088 0xffffffff,
00089 0xffffffff,
00090 0xffffffff,
00091 0xffffffff,
00092 0xffffffff,
00093 0xffffffff,
00094 0xffffffff,
00095 0xffffffff,
00096 0xffffffff,
00097 0xffffffff,
00098 0xffffffff,
00099 0xffffffff,
00100 0xffffffff,
00101
00102
00103
00104 };
00105
00106
00107
00108
00109 static const char * const bd_psr_name[BD_PSR_COUNT] = {
00110 "IG_STREAM_ID",
00111 "PRIMARY_AUDIO_ID",
00112 "PG_STREAM",
00113 "ANGLE_NUMBER",
00114 "TITLE_NUMBER",
00115 "CHAPTER",
00116 "PLAYLIST",
00117 "PLAYITEM",
00118 "TIME",
00119 "NAV_TIMER",
00120 "SELECTED_BUTTON_ID",
00121 "MENU_PAGE_ID",
00122 "STYLE",
00123 "PARENTAL",
00124 "SECONDARY_AUDIO_VIDEO",
00125 "AUDIO_CAP",
00126 "AUDIO_LANG",
00127 "PG_AND_SUB_LANG",
00128 "PSR_MENU_LANG",
00129 "PSR_COUNTRY",
00130 "PSR_REGION",
00131 "PSR_VIDEO_CAP",
00132 };
00133
00134
00135
00136
00137
00138 typedef struct {
00139 void *handle;
00140 void (*cb)(void *, BD_PSR_EVENT*);
00141 } PSR_CB_DATA;
00142
00143 struct bd_registers_s
00144 {
00145 uint32_t psr[BD_PSR_COUNT];
00146 uint32_t gpr[BD_GPR_COUNT];
00147
00148
00149 unsigned num_cb;
00150 PSR_CB_DATA *cb;
00151
00152 BD_MUTEX mutex;
00153 };
00154
00155
00156
00157
00158
00159 BD_REGISTERS *bd_registers_init(void)
00160 {
00161 BD_REGISTERS *p = calloc(1, sizeof(BD_REGISTERS));
00162
00163 memcpy(p->psr, bd_psr_init, sizeof(bd_psr_init));
00164
00165 bd_mutex_init(&p->mutex);
00166
00167 return p;
00168 }
00169
00170 void bd_registers_free(BD_REGISTERS *p)
00171 {
00172 if (p) {
00173 bd_mutex_destroy(&p->mutex);
00174
00175 X_FREE(p->cb);
00176 }
00177
00178 X_FREE(p);
00179 }
00180
00181
00182
00183
00184
00185 void bd_psr_lock(BD_REGISTERS *p)
00186 {
00187 bd_mutex_lock(&p->mutex);
00188 }
00189
00190 void bd_psr_unlock(BD_REGISTERS *p)
00191 {
00192 bd_mutex_unlock(&p->mutex);
00193 }
00194
00195
00196
00197
00198
00199 void bd_psr_register_cb (BD_REGISTERS *p, void (*callback)(void*,BD_PSR_EVENT*), void *cb_handle)
00200 {
00201
00202 unsigned i;
00203
00204 bd_psr_lock(p);
00205
00206 for (i = 0; i < p->num_cb; i++) {
00207 if (p->cb[i].handle == cb_handle && p->cb[i].cb == callback) {
00208
00209 bd_psr_unlock(p);
00210 return;
00211 }
00212 }
00213
00214 p->num_cb++;
00215 p->cb = realloc(p->cb, p->num_cb * sizeof(PSR_CB_DATA));
00216
00217 p->cb[p->num_cb - 1].cb = callback;
00218 p->cb[p->num_cb - 1].handle = cb_handle;
00219
00220 bd_psr_unlock(p);
00221 }
00222
00223 void bd_psr_unregister_cb(BD_REGISTERS *p, void (*callback)(void*,BD_PSR_EVENT*), void *cb_handle)
00224 {
00225 unsigned i = 0;
00226
00227 bd_psr_lock(p);
00228
00229 while (i < p->num_cb) {
00230 if (p->cb[i].handle == cb_handle && p->cb[i].cb == callback) {
00231 if (--p->num_cb) {
00232 memmove(p->cb + i, p->cb + i + 1, sizeof(PSR_CB_DATA) * p->num_cb);
00233 continue;
00234 }
00235 }
00236 i++;
00237 }
00238
00239 bd_psr_unlock(p);
00240 }
00241
00242
00243
00244
00245
00246 void bd_psr_save_state(BD_REGISTERS *p)
00247 {
00248
00249
00250 bd_psr_lock(p);
00251
00252 memcpy(p->psr + 36, p->psr + 4, sizeof(uint32_t) * 5);
00253 memcpy(p->psr + 42, p->psr + 10, sizeof(uint32_t) * 3);
00254
00255
00256
00257 if (p->num_cb) {
00258 BD_PSR_EVENT ev = {
00259 .ev_type = BD_PSR_SAVE,
00260 .psr_idx = -1,
00261 .old_val = 0,
00262 .new_val = 0,
00263 };
00264
00265 unsigned j;
00266 for (j = 0; j < p->num_cb; j++) {
00267 p->cb[j].cb(p->cb[j].handle, &ev);
00268 }
00269 }
00270
00271 bd_psr_unlock(p);
00272 }
00273
00274 void bd_psr_reset_backup_registers(BD_REGISTERS *p)
00275 {
00276 bd_psr_lock(p);
00277
00278
00279 memcpy(p->psr + 36, bd_psr_init + 36, sizeof(uint32_t) * 5);
00280 memcpy(p->psr + 42, bd_psr_init + 42, sizeof(uint32_t) * 3);
00281
00282 bd_psr_unlock(p);
00283 }
00284
00285 void bd_psr_restore_state(BD_REGISTERS *p)
00286 {
00287 uint32_t old_psr[13];
00288 uint32_t new_psr[13];
00289
00290 bd_psr_lock(p);
00291
00292 if (p->num_cb) {
00293 memcpy(old_psr, p->psr, sizeof(old_psr[0]) * 13);
00294 }
00295
00296
00297 memcpy(p->psr + 4, p->psr + 36, sizeof(uint32_t) * 5);
00298 memcpy(p->psr + 10, p->psr + 42, sizeof(uint32_t) * 3);
00299
00300 if (p->num_cb) {
00301 memcpy(new_psr, p->psr, sizeof(new_psr[0]) * 13);
00302 }
00303
00304
00305 memcpy(p->psr + 36, bd_psr_init + 36, sizeof(uint32_t) * 5);
00306 memcpy(p->psr + 42, bd_psr_init + 42, sizeof(uint32_t) * 3);
00307
00308
00309 if (p->num_cb) {
00310 BD_PSR_EVENT ev;
00311 unsigned i, j;
00312
00313 ev.ev_type = BD_PSR_RESTORE;
00314
00315 for (i = 4; i < 13; i++) {
00316 if (i != PSR_NAV_TIMER) {
00317
00318 ev.psr_idx = i;
00319 ev.old_val = old_psr[i];
00320 ev.new_val = new_psr[i];
00321
00322 for (j = 0; j < p->num_cb; j++) {
00323 p->cb[j].cb(p->cb[j].handle, &ev);
00324 }
00325 }
00326 }
00327 }
00328
00329 bd_psr_unlock(p);
00330 }
00331
00332
00333
00334
00335
00336 int bd_gpr_write(BD_REGISTERS *p, int reg, uint32_t val)
00337 {
00338 if (reg < 0 || reg > BD_GPR_COUNT) {
00339 BD_DEBUG(DBG_BLURAY, "bd_gpr_write(%d): invalid register\n", reg);
00340 return -1;
00341 }
00342
00343 p->gpr[reg] = val;
00344 return 0;
00345 }
00346
00347 uint32_t bd_gpr_read(BD_REGISTERS *p, int reg)
00348 {
00349 if (reg < 0 || reg > BD_GPR_COUNT) {
00350 BD_DEBUG(DBG_BLURAY, "bd_gpr_read(%d): invalid register\n", reg);
00351 return -1;
00352 }
00353
00354 return p->gpr[reg];
00355 }
00356
00357
00358
00359
00360
00361 uint32_t bd_psr_read(BD_REGISTERS *p, int reg)
00362 {
00363 uint32_t val;
00364
00365 if (reg < 0 || reg > BD_PSR_COUNT) {
00366 BD_DEBUG(DBG_BLURAY, "bd_psr_read(%d): invalid register\n", reg);
00367 return -1;
00368 }
00369
00370 bd_psr_lock(p);
00371
00372 val = p->psr[reg];
00373
00374 bd_psr_unlock(p);
00375
00376 return val;
00377 }
00378
00379 int bd_psr_setting_write(BD_REGISTERS *p, int reg, uint32_t val)
00380 {
00381 if (reg < 0 || reg > BD_PSR_COUNT) {
00382 BD_DEBUG(DBG_BLURAY, "bd_psr_write(%d, %d): invalid register\n", reg, val);
00383 return -1;
00384 }
00385
00386 bd_psr_lock(p);
00387
00388 if (p->psr[reg] == val) {
00389 BD_DEBUG(DBG_BLURAY, "bd_psr_write(%d, %d): no change in value\n", reg, val);
00390 } else if (bd_psr_name[reg]) {
00391 BD_DEBUG(DBG_BLURAY, "bd_psr_write(): PSR%-4d (%s) 0x%x -> 0x%x\n", reg, bd_psr_name[reg], p->psr[reg], val);
00392 } else {
00393 BD_DEBUG(DBG_BLURAY, "bd_psr_write(): PSR%-4d 0x%x -> 0x%x\n", reg, p->psr[reg], val);
00394 }
00395
00396 if (p->num_cb) {
00397 BD_PSR_EVENT ev;
00398 unsigned i;
00399
00400 ev.ev_type = p->psr[reg] == val ? BD_PSR_WRITE : BD_PSR_CHANGE;
00401 ev.psr_idx = reg;
00402 ev.old_val = p->psr[reg];
00403 ev.new_val = val;
00404
00405 p->psr[reg] = val;
00406
00407 for (i = 0; i < p->num_cb; i++) {
00408 p->cb[i].cb(p->cb[i].handle, &ev);
00409 }
00410
00411 } else {
00412
00413 p->psr[reg] = val;
00414 }
00415
00416 bd_psr_unlock(p);
00417
00418 return 0;
00419 }
00420
00421 int bd_psr_write(BD_REGISTERS *p, int reg, uint32_t val)
00422 {
00423 if ((reg == 13) ||
00424 (reg >= 15 && reg <= 20) ||
00425 (reg >= 29 && reg <= 31) ||
00426 (reg >= 48 && reg <= 61)) {
00427 BD_DEBUG(DBG_BLURAY, "bd_psr_write(%d, %d): read-only register !\n", reg, val);
00428 return -2;
00429 }
00430
00431 return bd_psr_setting_write(p, reg, val);
00432 }
00433