root/trunk/libfreebob/tests/freebob-server.c

Revision 185, 12.3 kB (checked in by wagi, 16 years ago)

CVS-SVN migration developer public sync patch

Line 
1 /*
2 * avc_vcr.c - An example of an AV/C Tape Recorder target implementation
3 *
4 * Copyright Dan Dennedy <dan@dennedy.org>
5 *
6 * Inspired by virtual_vcr from Bonin Franck <boninf@free.fr>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software Foundation,
20 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 */
22
23 #include <sys/types.h>
24 #include <sys/time.h>
25 #include <sys/poll.h>
26
27 #include <stdio.h>
28 #include <errno.h>
29 #include <string.h>
30 #include <unistd.h>
31 #include <stdlib.h>
32 #include <signal.h>
33
34 #include <libraw1394/raw1394.h>
35 #include <libraw1394/csr.h>
36 #include <libavc1394/avc1394.h>
37 #include <libavc1394/rom1394.h>
38
39 const char not_compatible[] = "\n"
40         "This libraw1394 does not work with your version of Linux. You need a different\n"
41         "version that matches your kernel (see kernel help text for the raw1394 option to\n"
42         "find out which is the correct version).\n";
43
44 const char not_loaded[] = "\n"
45         "This probably means that you don't have raw1394 support in the kernel or that\n"
46         "you haven't loaded the raw1394 module.\n";
47
48
49 unsigned char g_signal_mode = 0x05; // SD 525-60, TODO: get from media
50 unsigned char g_transport_mode = AVC1394_VCR_CMD_WIND;
51 unsigned char g_transport_state = AVC1394_VCR_OPERAND_WIND_STOP;
52
53 static int g_done = 0;
54
55 static void sighandler (int sig)
56 {
57         printf("signal!\n");
58         g_done = 1;
59 }
60
61 /**** subunit handlers ****/
62 int subunit_control( avc1394_cmd_rsp *cr )
63 {
64         switch ( cr->opcode )
65         {
66         case AVC1394_VCR_CMD_PLAY:
67                 switch ( cr->operand[0] )
68                 {
69                 case AVC1394_VCR_OPERAND_PLAY_FORWARD:
70                         g_transport_mode = AVC1394_GET_OPCODE( AVC1394_VCR_RESPONSE_TRANSPORT_STATE_PLAY );
71                         g_transport_state = AVC1394_VCR_OPERAND_PLAY_FORWARD;
72                         cr->status = AVC1394_RESP_ACCEPTED;
73                         printf("PLAY FORWARD\n");
74                         break;
75                
76                 case AVC1394_VCR_OPERAND_PLAY_FASTEST_FORWARD:
77                         g_transport_mode = AVC1394_GET_OPCODE( AVC1394_VCR_RESPONSE_TRANSPORT_STATE_PLAY );
78                         g_transport_state = AVC1394_VCR_OPERAND_PLAY_FASTEST_FORWARD;
79                         cr->status = AVC1394_RESP_ACCEPTED;
80                         printf("PLAY FASTEST FORWARD\n");
81                         break;
82                
83                 case AVC1394_VCR_OPERAND_PLAY_REVERSE_PAUSE:
84                         g_transport_mode = AVC1394_GET_OPCODE( AVC1394_VCR_RESPONSE_TRANSPORT_STATE_PLAY );
85                         g_transport_state = cr->operand[0];
86                         cr->status = AVC1394_RESP_ACCEPTED;
87                         printf("PAUSE PLAY\n");
88                         break;
89                
90                 case AVC1394_VCR_OPERAND_PLAY_REVERSE:
91                         g_transport_mode = AVC1394_GET_OPCODE( AVC1394_VCR_RESPONSE_TRANSPORT_STATE_PLAY );
92                         g_transport_state = AVC1394_VCR_OPERAND_PLAY_REVERSE;
93                         cr->status = AVC1394_RESP_ACCEPTED;
94                         printf("PLAY REVERSE\n");
95                         break;
96
97                 case AVC1394_VCR_OPERAND_PLAY_FASTEST_REVERSE:
98                         g_transport_mode = AVC1394_GET_OPCODE( AVC1394_VCR_RESPONSE_TRANSPORT_STATE_PLAY );
99                         g_transport_state = AVC1394_VCR_OPERAND_PLAY_FASTEST_REVERSE;
100                         cr->status = AVC1394_RESP_ACCEPTED;
101                         printf("PLAY FASTEST REVERSE\n");
102                         break;
103                
104                 case AVC1394_VCR_OPERAND_PLAY_NEXT_FRAME:
105                         g_transport_mode = AVC1394_GET_OPCODE( AVC1394_VCR_RESPONSE_TRANSPORT_STATE_PLAY );
106                         g_transport_state = cr->operand[0];
107                         cr->status = AVC1394_RESP_ACCEPTED;
108                         printf("PLAY NEXT FRAME\n");
109                         break;
110                
111                 case AVC1394_VCR_OPERAND_PLAY_PREVIOUS_FRAME:
112                         g_transport_mode = AVC1394_GET_OPCODE( AVC1394_VCR_RESPONSE_TRANSPORT_STATE_PLAY );
113                         g_transport_state = cr->operand[0];
114                         cr->status = AVC1394_RESP_ACCEPTED;
115                         printf("PLAY PREVIOUS FRAME\n");
116                         break;
117                
118                 default:
119                         fprintf( stderr, "play mode 0x%02x non supported\n", cr->operand[0] );
120                         return 0;
121                 }
122                 break;
123
124         default:
125                 fprintf( stderr, "subunit control command 0x%02x non supported\n", cr->opcode );
126                 return 0;
127         }
128         return 1;
129 }
130
131
132 int subunit_status( avc1394_cmd_rsp *cr )
133 {
134         switch ( cr->opcode )
135         {
136         case AVC1394_VCR_CMD_OUTPUT_SIGNAL_MODE:
137                 cr->status = AVC1394_RESP_STABLE;
138                 cr->operand[0] = g_signal_mode;
139                 break;
140         default:
141                 fprintf( stderr, "subunit status command 0x%02x not supported\n", cr->opcode );
142                 return 0;
143         }
144         return 1;
145 }
146
147
148 int subunit_inquiry( avc1394_cmd_rsp *cr )
149 {
150         switch ( cr->opcode )
151         {
152         case AVC1394_VCR_CMD_PLAY:
153         case AVC1394_VCR_CMD_RECORD:
154         case AVC1394_VCR_CMD_WIND:
155         case AVC1394_VCR_CMD_OUTPUT_SIGNAL_MODE:
156         case AVC1394_VCR_CMD_INPUT_SIGNAL_MODE:
157         case AVC1394_VCR_CMD_TRANSPORT_STATE:
158         case AVC1394_VCR_CMD_TIME_CODE:
159         case AVC1394_VCR_CMD_MEDIUM_INFO:
160                 cr->status = AVC1394_RESP_IMPLEMENTED;
161                 return 1;
162         default:
163                 fprintf( stderr, "subunit inquiry command 0x%02x not supported\n", cr->opcode );
164                 return 0;
165         }
166         return 1;
167 }
168
169
170 /**** Unit handlers ****/
171 int unit_control( avc1394_cmd_rsp *cr )
172 {
173         switch ( cr->opcode )
174         {
175         default:
176                 fprintf( stderr, "unit control command 0x%02x not supported\n", cr->opcode );
177                 return 0;
178         }
179         return 1;
180 }
181
182
183 int unit_status( avc1394_cmd_rsp *cr )
184 {
185         cr->operand[1] = 0xff;
186         cr->operand[2] = 0xff;
187         cr->operand[3] = 0xff;
188         cr->operand[4] = 0xff;
189         switch ( cr->opcode )
190         {
191         case AVC1394_CMD_UNIT_INFO:
192                 cr->status = AVC1394_RESP_STABLE;
193                 cr->operand[0] = AVC1394_OPERAND_UNIT_INFO_EXTENSION_CODE;
194                 cr->operand[1] = AVC1394_SUBUNIT_TYPE_TAPE_RECORDER >> 19;
195                 break;
196         case AVC1394_CMD_SUBUNIT_INFO:
197         {
198                 int page = ( cr->operand[0] >> 4 ) & 7;
199                 if ( page == 0 )
200                 {
201                         cr->status = AVC1394_RESP_STABLE;
202                         cr->operand[0] = (page << 4) | AVC1394_OPERAND_UNIT_INFO_EXTENSION_CODE;
203                         cr->operand[1] = AVC1394_SUBUNIT_TYPE_TAPE_RECORDER >> 19 << 3;
204                 }
205
206                 else
207                 {
208                         fprintf( stderr, "invalid page %d for subunit\n", page );
209                         return 0;
210                 }
211                 break;
212         }
213         default:
214                 fprintf( stderr, "unit status command 0x%02x not supported\n", cr->opcode );
215                 return 0;
216         }
217         return 1;
218 }
219
220
221 int unit_inquiry( avc1394_cmd_rsp *cr )
222 {
223         switch ( cr->opcode )
224         {
225         case AVC1394_CMD_SUBUNIT_INFO:
226         case AVC1394_CMD_UNIT_INFO:
227                 cr->status = AVC1394_RESP_IMPLEMENTED;
228         default:
229                 fprintf( stderr, "unit inquiry command 0x%02x not supported\n", cr->opcode );
230                 return 0;
231         }
232         return 1;
233 }
234
235
236 /**** primary avc1394 target callback ****/
237 int command_handler( avc1394_cmd_rsp *cr )
238 {
239         switch ( cr->subunit_type )
240         {
241         case AVC1394_SUBUNIT_TAPE_RECORDER:
242                 if ( cr->subunit_id != 0 )
243                 {
244                         fprintf( stderr, "subunit id 0x%02x not supported\n", cr->subunit_id );
245                         return 0;
246                 }
247                 switch ( cr->status )
248                 {
249                 case AVC1394_CTYP_CONTROL:
250                         return subunit_control( cr );
251                         break;
252                 case AVC1394_CTYP_STATUS:
253                         return subunit_status( cr );
254                         break;
255                 case AVC1394_CTYP_GENERAL_INQUIRY:
256                         return subunit_inquiry( cr );
257                         break;
258                 }
259                 break;
260         case AVC1394_SUBUNIT_UNIT:
261                 switch ( cr->status )
262                 {
263                 case AVC1394_CTYP_CONTROL:
264                         return unit_control( cr );
265                         break;
266                 case AVC1394_CTYP_STATUS:
267                         return unit_status( cr );
268                         break;
269                 case AVC1394_CTYP_GENERAL_INQUIRY:
270                         return unit_inquiry( cr );
271                         break;
272                 }
273                 break;
274         default:
275                 fprintf( stderr, "subunit type 0x%02x not supported\n", cr->subunit_type );
276                 return 0;
277         }
278         return 1;
279 }
280
281 struct configrom_backup {
282         quadlet_t rom[0x100];
283         size_t rom_size;
284         unsigned char rom_version;
285        
286 };
287
288 struct configrom_backup save_config_rom(raw1394handle_t handle)
289 {
290         int retval;
291         struct configrom_backup tmp;
292         /* get the current rom image */
293         retval=raw1394_get_config_rom(handle, tmp.rom, 0x100, &tmp.rom_size, &tmp.rom_version);
294 //      tmp.rom_size=rom1394_get_size(tmp.rom);
295         printf("save_config_rom get_config_rom returned %d, romsize %d, rom_version %d:\n",retval,tmp.rom_size,tmp.rom_version);
296
297         return tmp;
298 }
299
300 int restore_config_rom(raw1394handle_t handle, struct configrom_backup old)
301 {
302         int retval,i ;
303
304         quadlet_t current_rom[0x100];
305         size_t current_rom_size;
306         unsigned char current_rom_version;
307
308         retval=raw1394_get_config_rom(handle, current_rom, 0x100, &current_rom_size, &current_rom_version);
309         printf("restore_config_rom get_config_rom returned %d, romsize %d, rom_version %d:\n",retval,current_rom_size,current_rom_version);
310
311         printf("restore_config_rom restoring to romsize %d, rom_version %d:\n",old.rom_size,old.rom_version);
312
313         retval = raw1394_update_config_rom(handle, old.rom, old.rom_size, current_rom_version);
314         printf("restore_config_rom update_config_rom returned %d\n",retval);
315
316         /* get the current rom image */
317         retval=raw1394_get_config_rom(handle, current_rom, 0x100, &current_rom_size, &current_rom_version);
318         current_rom_size = rom1394_get_size(current_rom);
319         printf("get_config_rom returned %d, romsize %d, rom_version %d:",retval,current_rom_size,current_rom_version);
320         for (i = 0; i < current_rom_size; i++)
321         {
322                 if (i % 4 == 0) printf("\n0x%04x:", CSR_CONFIG_ROM+i*4);
323                 printf(" %08x", ntohl(current_rom[i]));
324         }
325         printf("\n");
326
327         return retval;
328 }
329
330 int init_config_rom(raw1394handle_t handle)
331 {
332         int retval, i;
333         quadlet_t rom[0x100];
334         size_t rom_size;
335         unsigned char rom_version;
336         rom1394_directory dir;
337         char *leaf;
338        
339         /* get the current rom image */
340         retval=raw1394_get_config_rom(handle, rom, 0x100, &rom_size, &rom_version);
341         rom_size = rom1394_get_size(rom);
342         printf("get_config_rom returned %d, romsize %d, rom_version %d:",retval,rom_size,rom_version);
343         for (i = 0; i < rom_size; i++)
344         {
345                 if (i % 4 == 0) printf("\n0x%04x:", CSR_CONFIG_ROM+i*4);
346                 printf(" %08x", ntohl(rom[i]));
347         }
348         printf("\n");
349        
350         /* get the local directory */
351         rom1394_get_directory( handle, raw1394_get_local_id(handle) & 0x3f, &dir);
352        
353         /* change the vendor description for kicks */
354         i = strlen(dir.textual_leafs[0]);
355         strncpy(dir.textual_leafs[0], "FreeBob Server                            ", i);
356         retval = rom1394_set_directory(rom, &dir);
357         printf("rom1394_set_directory returned %d, romsize %d:",retval,rom_size);
358         for (i = 0; i < rom_size; i++)
359         {
360                 if (i % 4 == 0) printf("\n0x%04x:", CSR_CONFIG_ROM+i*4);
361                 printf(" %08x", ntohl(rom[i]));
362         }
363         printf("\n");
364        
365         /* free the allocated mem for the textual leaves */
366         rom1394_free_directory( &dir);
367        
368         /* add an AV/C unit directory */
369         dir.unit_spec_id    = 0x0000a02d;
370         dir.unit_sw_version = 0x00010001;
371         leaf = "freebob-server";
372         dir.nr_textual_leafs = 1;
373         dir.textual_leafs = &leaf;
374        
375         /* manipulate the rom */
376         retval = rom1394_add_unit( rom, &dir);
377        
378         /* get the computed size of the rom image */
379         rom_size = rom1394_get_size(rom);
380        
381         printf("rom1394_add_unit_directory returned %d, romsize %d:",retval,rom_size);
382         for (i = 0; i < rom_size; i++)
383         {
384                 if (i % 4 == 0) printf("\n0x%04x:", CSR_CONFIG_ROM+i*4);
385                 printf(" %08x", ntohl(rom[i]));
386         }
387         printf("\n");
388        
389         /* convert computed rom size from quadlets to bytes before update */
390         rom_size *= sizeof(quadlet_t);
391         retval = raw1394_update_config_rom(handle, rom, rom_size, rom_version);
392         printf("update_config_rom returned %d\n",retval);
393        
394         retval=raw1394_get_config_rom(handle, rom, 0x100, &rom_size, &rom_version);
395         printf("get_config_rom returned %d, romsize %d, rom_version %d:",retval,rom_size,rom_version);
396         for (i = 0; i < rom_size; i++)
397         {
398                 if (i % 4 == 0) printf("\n0x%04x:", CSR_CONFIG_ROM+i*4);
399                 printf(" %08x", ntohl(rom[i]));
400         }
401         printf("\n");
402        
403 //      printf("You need to reload your ieee1394 modules to reset the rom.\n");
404        
405         return 0;
406 }
407
408
409 int main( int argc, char **argv )
410 {
411         raw1394handle_t handle;
412
413         signal (SIGINT, sighandler);
414         signal (SIGPIPE, sighandler);
415
416         handle = raw1394_new_handle();
417
418         if ( !handle )
419         {
420                 if ( !errno )
421                 {
422                         printf( not_compatible );
423                 }
424                 else
425                 {
426                         perror( "couldn't get handle" );
427                         printf( not_loaded );
428                 }
429                 exit( EXIT_FAILURE );
430         }
431
432         if ( raw1394_set_port( handle, 0 ) < 0 )
433         {
434                 perror( "couldn't set port" );
435                 exit( EXIT_FAILURE );
436         }
437
438         struct configrom_backup cfgrom_backup;
439         cfgrom_backup=save_config_rom( handle );
440
441         if ( init_config_rom( handle ) < 0 )
442         {
443                 perror( "couldn't init config rom!" );
444                 exit( EXIT_FAILURE );
445         }
446
447
448         avc1394_init_target( handle, command_handler );
449        
450         printf( "Starting AV/C target; press Ctrl+C to quit...\n" );
451         struct pollfd pfd = {
452                 fd: raw1394_get_fd (handle),
453                 events: POLLIN | POLLPRI,
454                 revents: 0
455         };
456         int result = 0;
457        
458
459         do {
460                 if (poll (&pfd, 1, 100) > 0 && (pfd.revents & POLLIN))
461                 result = raw1394_loop_iterate (handle);
462                
463         } while (g_done == 0 && result == 0);
464        
465         avc1394_close_target( handle );
466        
467         restore_config_rom( handle, cfgrom_backup);
468
469         printf( "Bye...\n" );
470         exit( EXIT_SUCCESS );
471 }
Note: See TracBrowser for help on using the browser.