MythTV  0.26-pre
register.c
Go to the documentation of this file.
00001 /*
00002  * This file is part of libbluray
00003  * Copyright (C) 2010  hpi1
00004  *
00005  * This library is free software; you can redistribute it and/or
00006  * modify it under the terms of the GNU Lesser General Public
00007  * License as published by the Free Software Foundation; either
00008  * version 2.1 of the License, or (at your option) any later version.
00009  *
00010  * This library is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013  * Lesser General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU Lesser General Public
00016  * License along with this library. If not, see
00017  * <http://www.gnu.org/licenses/>.
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  * Initial values for player status/setting registers (5.8.2).
00034  *
00035  * PS in comment indicates player setting -> register can't be changed from movie object code.
00036  */
00037 
00038 static const uint32_t bd_psr_init[BD_PSR_COUNT] = {
00039     1,           /*     PSR0:  Interactive graphics stream number */
00040     0xff,        /*     PSR1:  Primary audio stream number */
00041     0x0fff0fff,  /*     PSR2:  PG TextST stream number and PiP PG stream number*/
00042     1,           /*     PSR3:  Angle number */
00043     0xffff,      /*     PSR4:  Title number */
00044     0xffff,      /*     PSR5:  Chapter number */
00045     0,           /*     PSR6:  PlayList ID */
00046     0,           /*     PSR7:  PlayItem ID */
00047     0,           /*     PSR8:  Presentation time */
00048     0,           /*     PSR9:  Navigation timer */
00049     0xffff,      /*     PSR10: Selected button ID */
00050     0,           /*     PSR11: Page ID */
00051     0xff,        /*     PSR12: User style number */
00052     0xff,        /* PS: PSR13: User age */
00053     0xffff,      /*     PSR14: Secondary audio stream number and secondary video stream number */
00054     0xffff,      /* PS: PSR15: player capability for audio */
00055     0xffffff,    /* PS: PSR16: Language code for audio */
00056     0xffffff,    /* PS: PSR17: Language code for PG and Text subtitles */
00057     0xffffff,    /* PS: PSR18: Menu description language code */
00058     0xffff,      /* PS: PSR19: Country code */
00059     0x07,        /* PS: PSR20: Region code */ /* 1 - A, 2 - B, 4 - C */
00060     0,           /*     PSR21 */
00061     0,           /*     PSR22 */
00062     0,           /*     PSR23 */
00063     0,           /*     PSR24 */
00064     0,           /*     PSR25 */
00065     0,           /*     PSR26 */
00066     0,           /*     PSR27 */
00067     0,           /*     PSR28 */
00068     0x03,        /* PS: PSR29: player capability for video */
00069     0x1ffff,     /* PS: PSR30: player capability for text subtitle */
00070     0x080200,    /* PS: PSR31: Player profile and version */
00071     0,           /*     PSR32 */
00072     0,           /*     PSR33 */
00073     0,           /*     PSR34 */
00074     0,           /*     PSR35 */
00075     0xffff,      /*     PSR36: backup PSR4 */
00076     0xffff,      /*     PSR37: backup PSR5 */
00077     0,           /*     PSR38: backup PSR6 */
00078     0,           /*     PSR39: backup PSR7 */
00079     0,           /*     PSR40: backup PSR8 */
00080     0,           /*     PSR41: */
00081     0xffff,      /*     PSR42: backup PSR10 */
00082     0,           /*     PSR43: backup PSR11 */
00083     0xff,        /*     PSR44: backup PSR12 */
00084     0,           /*     PSR45: */
00085     0,           /*     PSR46: */
00086     0,           /*     PSR47: */
00087     0xffffffff,  /* PS: PSR48: Characteristic text caps */
00088     0xffffffff,  /* PS: PSR49: Characteristic text caps */
00089     0xffffffff,  /* PS: PSR50: Characteristic text caps */
00090     0xffffffff,  /* PS: PSR51: Characteristic text caps */
00091     0xffffffff,  /* PS: PSR52: Characteristic text caps */
00092     0xffffffff,  /* PS: PSR53: Characteristic text caps */
00093     0xffffffff,  /* PS: PSR54: Characteristic text caps */
00094     0xffffffff,  /* PS: PSR55: Characteristic text caps */
00095     0xffffffff,  /* PS: PSR56: Characteristic text caps */
00096     0xffffffff,  /* PS: PSR57: Characteristic text caps */
00097     0xffffffff,  /* PS: PSR58: Characteristic text caps */
00098     0xffffffff,  /* PS: PSR59: Characteristic text caps */
00099     0xffffffff,  /* PS: PSR60: Characteristic text caps */
00100     0xffffffff,  /* PS: PSR61: Characteristic text caps */
00101     /* 62-95:   reserved */
00102     /* 96-111:  reserved for BD system use */
00103     /* 112-127: reserved */
00104 };
00105 
00106 /*
00107  * PSR ids for debugging
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  * data
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     /* callbacks */
00149     unsigned     num_cb;
00150     PSR_CB_DATA *cb;
00151 
00152     BD_MUTEX     mutex;
00153 };
00154 
00155 /*
00156  * init / free
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  * PSR lock / unlock
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  * PSR change callback register / unregister
00197  */
00198 
00199 void bd_psr_register_cb  (BD_REGISTERS *p, void (*callback)(void*,BD_PSR_EVENT*), void *cb_handle)
00200 {
00201     /* no duplicates ! */
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  * PSR state save / restore
00244  */
00245 
00246 void bd_psr_save_state(BD_REGISTERS *p)
00247 {
00248     /* store registers 4-8 and 10-12 to backup registers */
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     /* generate save event */
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     /* init backup registers to default */
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     /* restore backup registers */
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     /* init backup registers to default */
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     /* generate restore events */
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  * GPR read / write
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  * PSR read / write
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 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends