18 #include <sys/types.h>
45 #define RESIZE(TO, NEW, pos) {\
48 if (pos > BURN_POS_END)\
50 if (pos == BURN_POS_END)\
52 if ((int) pos > TO->NEW##s)\
55 tmp = realloc(TO->NEW, sizeof(struct NEW *) * (TO->NEW##s + 1));\
59 memmove(TO->NEW + pos + 1, TO->NEW + pos,\
60 sizeof(struct NEW *) * (TO->NEW##s - pos));\
74 #ifdef Libburn_disc_with_incomplete_sessioN
75 d->incomplete_sessions= 0;
109 for (i = 0; i < 8; i++) {
132 for (i = 0; i < s->
tracks; i++)
134 for (i = 0; i < 8; i++)
185 for (i = 0; i < 100; i++)
186 t->
index[i] = 0x7fffffff;
226 for (i = 0; i < 8; i++)
241 for (i = 0; i < 8; i++)
263 if (s->
track == NULL)
269 for (i = 0; i < s->
tracks; i++) {
270 if (t == s->
track[i]) {
280 if (pos != s->
tracks - 1) {
297 sprintf(msg,
"This disc has %d sessions", d->
sessions);
310 sprintf(msg,
" Session has %d tracks", s->
tracks);
314 for (i = 0; i < s->
tracks; i++) {
322 sprintf(msg,
" track size %d sectors",
334 unsigned char ctladr;
342 "Attempt to set track mode to unusable value 0x%X",
343 (
unsigned int)
mode);
370 if (value < 0 || value > 1)
378 unsigned char year,
unsigned int serial)
385 for (i = 0; i < 2; ++i) {
392 if (! ((country[i] >=
'0' && country[i] <=
'9') ||
393 (country[i] >=
'a' && country[i] <=
'z') ||
394 (country[i] >=
'A' && country[i] <=
'Z') ) )
399 for (i = 0; i < 3; ++i) {
406 if (! ((owner[i] >=
'0' && owner[i] <=
'9') ||
407 (owner[i] >=
'a' && owner[i] <=
'z') ||
408 (owner[i] >=
'A' && owner[i] <=
'Z') ) )
434 "Attempt to set ISRC with bad data", 0, 0);
442 unsigned int serial = 2000000000;
444 if (strlen(
isrc) != 12 ||
448 "Attempt to set ISRC with bad data", 0, 0);
451 year = (
isrc[5] -
'0') * 10 + (
isrc[6] -
'0');
453 sscanf(
isrc + 7,
"%u", &serial);
465 unsigned int relative_lba,
int flag)
467 if (index_number < 0 || index_number > 99) {
470 "Bad track index number", 0, 0);
476 t->
index[index_number] = relative_lba;
477 if (index_number >= t->
indices)
487 for (i = 0; i < 100; i++)
488 t->
index[i] = 0x7fffffff;
529 }
else if(t->
entry != NULL) {
536 sectors = size / seclen;
555 size = seclen * (off_t) sectors - (off_t) t->
offset - (off_t) t->
tail;
592 int max_sectors, ret = 2;
597 max_sectors = max_size / 2048;
599 sprintf(msg,
"Setting total track size to %ds (payload %ds)\n",
600 max_sectors & 0x7fffffff,
637 off_t *read_bytes, off_t *written_bytes)
662 return seclen - size % seclen;
670 for (i = 0; i < s->
tracks; i++)
687 if (t->
entry == NULL)
705 #ifdef Libburn_disc_with_incomplete_sessioN
707 *num = d->
sessions - d->incomplete_sessions;
723 #ifdef Libburn_disc_with_incomplete_sessioN
725 return d->incomplete_sessions;
755 int sidx= 0, tidx= 0, ret, track_offset, alloc_len = 34;
759 char *msg_data = NULL, *msg;
760 struct buffer *buf = NULL;
766 "Damaged CD table-of-content detected and truncated.");
767 strcat(msg_data,
" In burn_disc_cd_toc_extensions: ");
768 msg = msg_data + strlen(msg_data);
770 strcpy(msg,
"d->session == NULL");
778 for (sidx = 0; sidx < d->
sessions; sidx++) {
780 if (track_offset <= 0)
782 if (d->
session[sidx] == NULL) {
783 sprintf(msg,
"d->session[%d of %d] == NULL",
788 sprintf(msg,
"d->session[%d of %d]->track == NULL",
794 " Session %d of %d: Leadout entry missing.",
798 for (tidx = 0; tidx < d->
session[sidx]->
tracks + 1; tidx++) {
799 if (tidx < d->session[sidx]->tracks) {
802 "d->session[%d of %d]->track[%d of %d] == NULL",
809 "session %d of %d, track %d of %d, entry == NULL",
829 tidx - 1 + track_offset, buf,
834 if (ret < prev_entry->track_blocks &&
836 ret < prev_entry->track_blocks - 2))
866 if (tno < 1 || tno > 99) {
869 "CD start track number exceeds range of 1 to 99",
873 if (tno + session->
tracks - 1 > 99) {
876 "CD track number exceeds 99", 0, 0);
925 static char *pack_type_names[] = {
930 if (pack_type_names[i][0] == 0)
932 for (j = 0; pack_type_names[i][j]; j++)
933 if (pack_type_names[i][j] != pack_type_name[j] &&
934 tolower(pack_type_names[i][j]) !=
937 if (pack_type_names[i][j] == 0)
947 int pack_type,
char *pack_type_name,
953 if (pack_type_name != NULL)
954 if (pack_type_name[0])
960 "CD-TEXT pack type out of range", 0, 0);
977 t->
flags = (t->
flags & ~(1 << i)) | (flag & (1 << i));
984 char *pack_type_name,
987 if (pack_type_name != NULL)
988 if (pack_type_name[0])
994 "CD-TEXT pack type out of range", 0, 0);
1005 if (block < 0 || block > 7) {
1008 "CD-TEXT block number out of range", 0, 0);
1019 int pack_type,
char *pack_type_name,
1035 int pack_type,
char *pack_type_name,
1042 if (t->
cdtext[block] == NULL) {
1059 for (i= 0; i < 8; i++)
1074 int pack_type,
char *pack_type_name,
1090 int pack_type,
char *pack_type_name,
1098 if (s->
cdtext[block] == NULL) {
1111 int char_codes[8],
int copyrights[8],
1112 int block_languages[8],
int flag)
1116 for (i = 0; i < 8; i++) {
1117 if (char_codes[i] >= 0 && char_codes[i] <= 255)
1119 if (copyrights[i] >= 0 && copyrights[i] <= 255)
1121 if (block_languages[i] >= 0 && block_languages[i] <= 255)
1130 int char_codes[8],
int copyrights[8],
1131 int block_languages[8],
int flag)
1135 for (i = 0; i < 8; i++) {
1150 for (i= 0; i < 8; i++) {
1239 if (*victim == NULL)
1248 if (crs->
fifo != NULL)
1254 if (crs->
track != NULL)
1267 for (ept = text + strlen(text); ept > text; ept--)
1268 if (*(ept - 1) != 32 && *(ept - 1) != 9)
1270 if (text[0] ==
'"') {
1273 if (*(ept - 1) ==
'"')
1294 "In cue sheet file: Being set to ignore all CD-TEXT aspects",
1300 if ((flag & 1) &&
track == NULL) {
1303 "Track attribute set before first track in cue sheet file",
1311 if (
track != NULL) {
1313 (
unsigned char *) payload,
1314 strlen(payload) + 1, 0);
1317 (
unsigned char *) payload,
1318 strlen(payload) + 1, 0);
1330 if (crs->
track == NULL)
1336 "In cue sheet file: TRACK without INDEX 01", 0, 0);
1342 "No INDEX 01 defined for last TRACK in cue sheet file",
1346 if (session->
tracks == 0) {
1355 "CD track number exceeds 99",
1383 int ret, at_end = 0;
1384 char *apt, *msg = NULL;
1386 for(apt = *payload; *apt != 0 && *apt != 32 && *apt != 9; apt++);
1389 else if (!(flag & 1))
1391 ret = sscanf(*payload,
"%d", number);
1395 "Unsuitable number in cue sheet file: '%.4000s'",
1404 for (apt++; *apt == 32 || *apt == 9; apt++);
1420 struct libdax_audioxtr *xtr= NULL;
1421 char *fmt, *fmt_info;
1422 int ret, num_channels, sample_rate, bits_per_sample, msb_first;
1431 &sample_rate, &bits_per_sample, &msb_first, 0);
1432 if ((flag & 255) == 1) {
1433 if (strcmp(fmt,
".wav") != 0) {
1435 "In cue sheet: Not recognized as WAVE : FILE '%.4000s'",
1446 "In cue sheet: Cannot get payload size of FILE '%.4000s'",
1456 "In cue sheet: Cannot represent payload as plain fd: FILE '%.4000s'",
1491 fd = open(path, O_RDONLY |
O_BINARY);
1494 "In cue sheet: Cannot open FILE '%.4000s'",
1517 int ret, minute, second, frame;
1518 char *msg = NULL, msf[3], *msf_pt;
1521 if (strlen(apt) < 8) {
1524 "Inappropriate cue sheet file %s '%.4000s'",
1531 if (apt[2] !=
':' || apt[5] !=
':' ||
1532 (apt[8] != 0 && apt[8] != 32 && apt[8] != 9))
1536 strncpy(msf, apt, 2);
1540 strncpy(msf, apt + 3, 2);
1544 strncpy(msf, apt + 6, 2);
1549 *file_ba = ((minute * 60) + second ) * 75 + frame;
1562 if (crs->
track == NULL) {
1564 sprintf(msg,
"In cue sheet file: %s found before TRACK",
1581 int ret, mode, index_no, file_ba, chunks;
1582 int block_size, step, audio_xtr = 0;
1584 char *cmd, *apt, *msg = NULL, *cpt, *filetype;
1591 if (line[0] == 0 || line[0] ==
'#') {
1595 for (cmd = line; *cmd == 32 || *cmd == 9; cmd++);
1596 for(apt = cmd; *apt != 0 && *apt != 32 && *apt != 9; apt++);
1599 for (apt++; *apt == 32 || *apt == 9; apt++);
1602 if (strcmp(cmd,
"ARRANGER") == 0) {
1607 }
else if (strcmp(cmd,
"CATALOG") == 0) {
1608 for (cpt = apt; (cpt - apt) < 13 && *cpt == (*cpt & 0x7f);
1610 if ((cpt - apt) < 13) {
1613 "In cue sheet file: Inappropriate content of CATALOG",
1625 }
else if (strcmp(cmd,
"CDTEXTFILE") == 0) {
1637 "Out of virtual memory", 0, 0);
1641 }
else if (strcmp(cmd,
"COMPOSER") == 0) {
1646 }
else if (strcmp(cmd,
"FILE") == 0) {
1650 "In cue sheet file: Multiple occurrences of FILE",
1655 for (cpt = apt + (strlen(apt) - 1);
1656 cpt > apt && (*cpt == 32 || *cpt == 9); cpt--);
1658 for (; cpt > apt && *cpt != 32 && *cpt != 9; cpt--);
1662 "In cue sheet file: FILE without type word",
1668 if (strcmp(filetype,
"BINARY") == 0) {
1670 }
else if (strcmp(filetype,
"MOTOROLA") == 0) {
1672 }
else if (strcmp(filetype,
"WAVE") == 0) {
1676 "In cue sheet file: Unsupported FILE type '%.4000s'",
1688 ret = stat(apt, &stbuf);
1692 "In cue sheet file: Unusable FILE '%.4000s'",
1699 if (!S_ISREG(stbuf.st_mode))
1700 goto not_usable_file;
1711 }
else if (strcmp(cmd,
"FLAGS") == 0) {
1716 if (strncmp(apt,
"DCP", 3) == 0) {
1719 }
else if (strncmp(apt,
"4CH", 3) == 0) {
1722 }
else if (strncmp(apt,
"PRE", 3) == 0) {
1725 }
else if (strncmp(apt,
"SCMS", 4) == 0) {
1731 *cpt != 32 && *cpt != 9 && *cpt != 0; cpt++);
1734 "In cue sheet file: Unknown FLAGS option '%.4000s'",
1745 if (apt[step] != 0 && apt[step] != 32 &&
1748 for (apt += step; *apt == 32 || *apt == 9; apt++);
1752 }
else if (strcmp(cmd,
"INDEX") == 0) {
1763 if (file_ba < crs->prev_file_ba) {
1767 "Backward INDEX address in cue sheet file",
1771 if (file_ba < crs->current_index_ba)
1772 goto overlapping_ba;
1777 goto overlapping_ba;
1784 "Unacceptable INDEX number in cue sheet file",
1817 if (crs->
fifo == NULL) {
1821 if (crs->
fifo != NULL)
1822 inp_src = crs->
fifo;
1826 (off_t) (file_ba * crs->
block_size), (off_t) 0, 1);
1846 }
else if (strcmp(cmd,
"ISRC") == 0) {
1860 }
else if (strcmp(cmd,
"MESSAGE") == 0) {
1865 }
else if (strcmp(cmd,
"PERFORMER") == 0) {
1870 }
else if (strcmp(cmd,
"POSTGAP") == 0) {
1882 }
else if (strcmp(cmd,
"PREGAP") == 0) {
1894 }
else if (strcmp(cmd,
"REM") == 0) {
1897 }
else if (strcmp(cmd,
"SONGWRITER") == 0) {
1902 }
else if (strcmp(cmd,
"TITLE") == 0) {
1907 }
else if (strcmp(cmd,
"TRACK") == 0) {
1911 "No FILE defined before TRACK in cue sheet file",
1925 "Inappropriate cue sheet file track number %d",
1932 if (strcmp(apt,
"AUDIO") == 0) {
1935 }
else if (strcmp(apt,
"MODE1/2048") == 0) {
1940 "Unsupported cue sheet file track datatype '%.4000s'",
1951 "In cue sheet file: Unsupported mix track block sizes",
1958 if (crs->
track == NULL)
1968 sprintf(msg,
"Unknown cue sheet file command '%.4000s'", line);
1989 unsigned char **text_packs,
int *num_packs,
int flag)
1991 int ret, num_tracks, i, pack_type, length, double_byte = 0;
1992 int line_counter = 0;
1994 char *msg = NULL, *line = NULL;
1995 unsigned char *payload;
2000 static unsigned char dummy_cdtext[2] = {0, 0};
2004 if (text_packs != NULL)
2019 if (num_tracks > 0) {
2021 "Cue sheet file reader called while session has already defined tracks");
2027 if (stat(path, &stbuf) == -1) {
2029 sprintf(msg,
"Cannot open cue sheet file '%.4000s'",
2036 if (!S_ISREG(stbuf.st_mode)) {
2038 "File is not of usable type: Cue sheet file '%.4000s'",
2046 fp = fopen(path,
"rb");
2055 "Cannot read all bytes from cue sheet file '%.4000s'",
2066 "Cue sheet file '%.4000s': Reading aborted after line %d",
2067 path, line_counter);
2076 if (crs->
track != NULL) {
2081 "No INDEX 01 defined for last TRACK in cue sheet file",
2089 "TRACK start time point exceeds size of FILE from cue sheet file",
2103 if (text_packs == NULL) {
2109 text_packs, num_packs, 0);
2117 for (pack_type = 0x80; pack_type < 0x8f; pack_type++) {
2118 if (pack_type > 0x86 && pack_type != 0x8e)
2121 &payload, &length, 0);
2124 if (payload != NULL)
2126 for (i = 0; i < num_tracks; i++) {
2128 "", &payload, &length, 0);
2131 double_byte = (ret > 1);
2132 if (payload != NULL)
2135 if (i < num_tracks) {
2137 "", dummy_cdtext, 1 + double_byte,
2147 for (i = 0; i < num_tracks; i++)
2149 if(text_packs != NULL) {
2150 if(*text_packs != NULL)
int burn_cdtext_from_packfile(char *path, unsigned char **text_packs, int *num_packs, int flag)
struct burn_source * burn_offst_source_new(struct burn_source *inp, struct burn_source *prev, off_t start, off_t size, int flag)
struct burn_source * burn_fifo_source_new(struct burn_source *inp, int chunksize, int chunks, int flag)
struct burn_source * burn_fd_source_new(int datafd, int subfd, off_t size)
void * burn_alloc_mem(size_t size, size_t count, int flag)
#define BURN_FREE_MEM(pt)
#define BURN_ALLOC_MEM(pt, typ, count)
char * burn_sfile_fgets(char *line, int maxl, FILE *fp)
char * burn_printify(char *msg)
int burn_msf_to_lba(int m, int s, int f)
int libdax_audioxtr_get_id(struct libdax_audioxtr *xtr, char **fmt, char **fmt_info, int *num_channels, int *sample_rate, int *bits_per_sample, int *msb_first, int flag)
void burn_source_free(struct burn_source *s)
enum burn_source_status burn_track_set_source(struct burn_track *t, struct burn_source *s)
int libdax_audioxtr_get_size(struct libdax_audioxtr *o, off_t *size, int flag)
int libdax_audioxtr_destroy(struct libdax_audioxtr **xtr, int flag)
int libdax_audioxtr_new(struct libdax_audioxtr **xtr, char *path, int flag)
int libdax_audioxtr_detach_fd(struct libdax_audioxtr *o, int *fd, int flag)
int libdax_msgs_submit(struct libdax_msgs *m, int origin, int error_code, int severity, int priority, char *msg_text, int os_errno, int flag)
#define LIBDAX_MSGS_SEV_DEBUG
#define LIBDAX_MSGS_SEV_FATAL
#define LIBDAX_MSGS_PRIO_HIGH
#define LIBDAX_MSGS_SEV_SORRY
#define LIBDAX_MSGS_SEV_WARNING
#define LIBDAX_MSGS_PRIO_ZERO
#define LIBDAX_MSGS_SEV_MISHAP
#define LIBDAX_MSGS_SEV_FAILURE
int mmc_four_char_to_int(unsigned char *data)
int mmc_read_track_info(struct burn_drive *d, int trackno, struct buffer *buf, int alloc_len)
unsigned char data[65536+4096]
unsigned char * payload[0x10]
struct burn_source * file_source
struct burn_source * fifo
struct burn_track * track
struct burn_track * prev_track
struct burn_source * offst_source
struct burn_session ** session
int current_is_cd_profile
unsigned char cdtext_char_code[8]
unsigned char cdtext_language[8]
unsigned char cdtext_copyright[8]
unsigned char mediacatalog[14]
struct burn_cdtext * cdtext[8]
struct burn_toc_entry * leadout_entry
struct burn_track ** track
int(* set_size)(struct burn_source *source, off_t size)
off_t(* get_size)(struct burn_source *)
unsigned char extensions_valid
unsigned char session_msb
struct burn_source * source
struct burn_cdtext * cdtext[8]
struct burn_toc_entry * entry
off_t burn_track_get_default_size(struct burn_track *t)
int burn_session_get_sectors(struct burn_session *s)
static int cue_create_file_source(char *path, struct burn_cue_file_cursor *crs, int flag)
int burn_track_set_byte_swap(struct burn_track *t, int swap_source_bytes)
void burn_track_free(struct burn_track *t)
int burn_session_get_start_tno(struct burn_session *session, int flag)
void burn_structure_print_session(struct burn_session *s)
static int cue_read_timepoint_lba(char *apt, char *purpose, int *file_ba, int flag)
int burn_track_set_postgap_size(struct burn_track *t, int size, int flag)
void burn_track_get_entry(struct burn_track *t, struct burn_toc_entry *entry)
int burn_session_add_track(struct burn_session *s, struct burn_track *t, unsigned int pos)
void burn_session_free(struct burn_session *s)
int burn_disc_get_incomplete_sessions(struct burn_disc *d)
int burn_session_set_cdtext(struct burn_session *s, int block, int pack_type, char *pack_type_name, unsigned char *payload, int length, int flag)
int burn_track_get_cdtext(struct burn_track *t, int block, int pack_type, char *pack_type_name, unsigned char **payload, int *length, int flag)
static int cue_crs_destroy(struct burn_cue_file_cursor **victim, int flag)
int burn_track_set_fillup(struct burn_track *t, int fill_up_media)
struct burn_session * burn_session_create(void)
struct burn_cdtext * burn_cdtext_create(void)
static int burn_cdtext_name_to_type(char *pack_type_name)
int burn_track_get_mode(struct burn_track *track)
int burn_track_clear_indice(struct burn_track *t, int flag)
static int cue_check_for_track(struct burn_cue_file_cursor *crs, char *cmd, int flag)
#define RESIZE(TO, NEW, pos)
int burn_track_set_isrc_string(struct burn_track *t, char isrc[13], int flag)
struct libdax_msgs * libdax_messenger
int burn_track_set_index(struct burn_track *t, int index_number, unsigned int relative_lba, int flag)
void burn_session_get_leadout_entry(struct burn_session *s, struct burn_toc_entry *entry)
int burn_track_set_size(struct burn_track *t, off_t size)
void burn_track_clear_isrc(struct burn_track *t)
int burn_track_get_counters(struct burn_track *t, off_t *read_bytes, off_t *written_bytes)
int burn_track_set_cdtext(struct burn_track *t, int block, int pack_type, char *pack_type_name, unsigned char *payload, int length, int flag)
static int burn_cdtext_check_blockno(int block)
int burn_track_set_pregap_size(struct burn_track *t, int size, int flag)
int burn_disc_add_session(struct burn_disc *d, struct burn_session *s, unsigned int pos)
int burn_track_is_data_done(struct burn_track *t)
int burn_track_dispose_cdtext(struct burn_track *t, int block)
struct burn_track ** burn_session_get_tracks(struct burn_session *s, int *num)
static int cue_set_cdtext(struct burn_session *session, struct burn_track *track, int pack_type, char *text, struct burn_cue_file_cursor *crs, int flag)
static int cue_read_number(char **payload, int *number, int flag)
static int cue_interpret_line(struct burn_session *session, char *line, struct burn_cue_file_cursor *crs, int flag)
int burn_track_set_default_size(struct burn_track *t, off_t size)
struct burn_disc * burn_disc_create(void)
void burn_structure_print_track(struct burn_track *t)
void burn_track_set_isrc(struct burn_track *t, char *country, char *owner, unsigned char year, unsigned int serial)
static int cue_crs_new(struct burn_cue_file_cursor **reply, int flag)
int burn_session_set_start_tno(struct burn_session *session, int tno, int flag)
int burn_session_by_cue_file(struct burn_session *session, char *path, int fifo_size, struct burn_source **fifo, unsigned char **text_packs, int *num_packs, int flag)
int burn_track_get_sectors(struct burn_track *t)
struct burn_track * burn_track_create(void)
void burn_session_hide_first_track(struct burn_session *s, int onoff)
int burn_track_apply_fillup(struct burn_track *t, off_t max_size, int flag)
int burn_session_remove_track(struct burn_session *s, struct burn_track *t)
int burn_track_get_shortage(struct burn_track *t)
int burn_disc_get_sectors(struct burn_disc *d)
int burn_session_get_cdtext(struct burn_session *s, int block, int pack_type, char *pack_type_name, unsigned char **payload, int *length, int flag)
int burn_session_get_hidefirst(struct burn_session *session)
static int cue_open_audioxtr(char *path, struct burn_cue_file_cursor *crs, int *fd, int flag)
int burn_disc_cd_toc_extensions(struct burn_drive *drive, int flag)
int burn_session_dispose_cdtext(struct burn_session *s, int block)
int burn_session_get_cdtext_par(struct burn_session *s, int char_codes[8], int copyrights[8], int block_languages[8], int flag)
struct burn_session ** burn_disc_get_sessions(struct burn_disc *d, int *num)
void burn_disc_free(struct burn_disc *d)
int burn_session_set_cdtext_par(struct burn_session *s, int char_codes[8], int copyrights[8], int block_languages[8], int flag)
void burn_cdtext_free(struct burn_cdtext **cdtext)
int burn_track_get_sectors_2(struct burn_track *t, int flag)
static int burn_cdtext_get(struct burn_cdtext *t, int pack_type, char *pack_type_name, unsigned char **payload, int *length, int flag)
int burn_track_set_sectors(struct burn_track *t, int sectors)
int burn_track_is_open_ended(struct burn_track *t)
int burn_disc_remove_session(struct burn_disc *d, struct burn_session *s)
static int burn_cdtext_set(struct burn_cdtext **cdtext, int pack_type, char *pack_type_name, unsigned char *payload, int length, int flag)
void burn_track_define_data(struct burn_track *t, int offset, int tail, int pad, int mode)
static int cue_attach_track(struct burn_session *session, struct burn_cue_file_cursor *crs, int flag)
int burn_track_set_cdxa_conv(struct burn_track *t, int value)
void burn_structure_print_disc(struct burn_disc *d)
static char * cue_unquote_text(char *text, int flag)
#define Libburn_pack_num_typeS
#define Libburn_pack_type_nameS
#define Libburn_pack_type_basE
int burn_sector_length(int tracktype)
void type_to_form(int mode, unsigned char *ctladr, int *form)