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; }