Hi,
From the linux-usb, I found "Philips PSC805 HID Report documentation",
but I found no tools to set the hid values, so with pieces of other hid
code, I wrote the attached hidset.c.
I wasn't sure where to send this source. If somewhere/someone else is
better, let me know.
PSC805, works with 'snd_usb_audio', but by default, does not output to
SPDIF.
To enable SPDIF output:
hidset ff000086 1
hidset ff000097 1
And if you want raw data to go over SPDIF, (so you can play ac3/a52
directly with something like 'cat song.ac3 | ac3spdif | aplay -t raw -f
dat -f S16_BE' )
hidset ff000088 1
-Don Mahurin
/* hidset
* Don Mahurin, 2006
* code from dumpev.c and hid-ups ( Paul Stewart)
*
* To enable spdif sound in a Philips psc805:
* hidset ff000086 1
* hidset ff000097 1
* To enable raw data stream passthrough (for a52,...)
* hidset ff000088 1
*/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#define HID_MAX_USAGES 1024
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <sys/signal.h>
#include <asm/types.h>
#include <linux/hiddev.h>
static inline int find_application(int fd, unsigned usage) {
int i = 0;
unsigned ret;
while ((ret = ioctl(fd, HIDIOCAPPLICATION, i)) != -1 &&
ret != usage) { printf("App: %08x\n", ret); i++; }
if (ret < 0) {
fprintf(stderr, "GUSAGE returns %x", ret);
perror("");
}
return (ret == usage);
}
static inline int find_usage_ref( int fd, int ucode, struct hiddev_usage_ref
*usage_ref)
{
int found = 0;
int report_type;
struct hiddev_report_info rep_info;
unsigned int alv, yalv;
struct hiddev_field_info field_info;
/* Initialise the internal report structures */
if (ioctl(fd, HIDIOCINITREPORT,0) < 0) {
return 0;
}
for (report_type = HID_REPORT_TYPE_MIN; report_type <= HID_REPORT_TYPE_MAX;
report_type++)
{
rep_info.report_type = report_type;
rep_info.report_id = HID_REPORT_ID_FIRST;
while (ioctl(fd, HIDIOCGREPORTINFO, &rep_info) >= 0)
{
#ifdef DEBUG
printf(" Report id: %d type: %d (%d fields)\n",
rep_info.report_id, rep_info.report_type, rep_info.num_fields);
#endif
for (alv = 0; alv < rep_info.num_fields; alv++)
{
memset(&field_info, 0, sizeof(field_info));
field_info.report_type = rep_info.report_type;
field_info.report_id = rep_info.report_id;
field_info.field_index = alv;
ioctl(fd, HIDIOCGFIELDINFO, &field_info);
#ifdef DEBUG
printf(" Field: %d: app: %04x phys %04x flags %x "
"(%d usages) unit %x exp %d\n",
alv, field_info.application, field_info.physical,
field_info.flags, field_info.maxusage, field_info.unit,
field_info.unit_exponent);
#endif
memset(usage_ref, 0, sizeof(*usage_ref));
for (yalv = 0; yalv < field_info.maxusage; yalv++)
{
usage_ref->report_type = field_info.report_type;
usage_ref->report_id = field_info.report_id;
usage_ref->field_index = alv;
usage_ref->usage_index = yalv;
ioctl(fd, HIDIOCGUCODE, usage_ref);
ioctl(fd, HIDIOCGUSAGE, usage_ref);
if(usage_ref->usage_code == ucode)
{
found = 1;
break;
}
}
if(found) break;
}
if(found) break;
rep_info.report_id |= HID_REPORT_ID_NEXT;
}
if(found) break;
}
return found;
}
int main (int argc, char **argv)
{
int fd = -1, i, found = 0;
struct hiddev_report_info rinfo;
struct hiddev_usage_ref uref;
int ucode;
int findex, uindex;
int value;
memset(&uref, 0, sizeof(uref));
argc--; argv++;
if(argc < 2)
{
printf("usage hidset USAGE_CODE VALUE\n");
return 1;
}
sscanf(*argv, "%x", &ucode);
argc--; argv++;
value = atoi(*argv);
argc--; argv++;
char evdev[20];
for (i = 0; i < 4; i++)
{
sprintf(evdev, "/dev/hiddev%d", i);
if ((fd = open(evdev, O_RDONLY)) >= 0) {
if (find_usage_ref(fd, ucode, &uref)) {
#ifdef DEBUG
printf("application usage code found.\n");
#endif
found = 1;
break;
}
}
}
if (! found) {
fprintf(stderr, "Couldn't find hiddev device.\n");
exit(1);
}
assert(uref.report_type == HID_REPORT_TYPE_OUTPUT);
printf ("changing value from %d to %d\n", uref.value, value);
uref.value = value;
/*fprintf(stderr,"u %u %u %u %u %x %d\n",
uref.report_type,
uref.report_id,
uref.field_index,
uref.usage_index,
uref.usage_code,
uref.value);
*/
if (ioctl(fd, HIDIOCSUSAGE, &uref) != 0) perror("SUSAGE/S");
rinfo.report_type = uref.report_type;
rinfo.report_id = uref.report_id;
if (ioctl(fd, HIDIOCSREPORT, &rinfo) != 0) perror("SREPORT/S");
return 0;
}