alsa support for qemu-user
PATCH 1/1 alsa support for qemu-user
alsa_bitfield
This patch implements a new type to the ioctl type list called "TYPE_BITFIELD". This is a more or less hacky fix to get bitfield definitions on different platforms do the same. The only case I needed it so far was a four-bit unsigned int so this is what is implemented. Run the appended "struct.c" on ppc and x86 to see what breaks.
alsa_ioctl
This patch should implement all currently available alsa ioctls. Maybe some of them are incorrect (different size) and some are prone to break when the host's long size is different from the targets. So far I get weird segmentation faults as soon as I include the struct definitions on anything but ppc so actually I haven't even tested that. I would very much appreciate it if anyone could look into this - I somehow can't imagine an enum to overflow.
ioctl_nodirection
Actually the direction given in the ioctl should be correct so we can assume the communication is uni-directional if IOC_R or IOC_W is given. The alsa developers did not like this concept though and declared ioctls IOC_R and IOC_W even though they were IOC_RW so alsa ioctls break when not being handled as RW.
ioctl_debug
This implements a simple search when an ioctl was not found to see if there is an ioctl available with a different size. This comes in very handy when implementing new ioctls.
Alex
thunk.h +3 -0
@@ -38,6 +38,7 @@ typedef enum argtype {TYPE_PTR ,TYPE_ARRAY ,TYPE_STRUCT , +TYPE_INTBITFIELD , } argtype;#define MK_PTR (type) TYPE_PTR, type
@@ -87,6 +88,7 @@ static inline int thunk_type_size(constcase TYPE_SHORT :return 2 ;case TYPE_INT : +case TYPE_INTBITFIELD :return 4 ;case TYPE_LONGLONG :case TYPE_ULONGLONG :
@@ -124,6 +126,7 @@ static inline int thunk_type_align(constcase TYPE_SHORT :return 2 ;case TYPE_INT : +case TYPE_INTBITFIELD :return 4 ;case TYPE_LONGLONG :case TYPE_ULONGLONG :
thunk.c +21 -0
@@ -40,6 +40,7 @@ static inline const argtype *thunk_type_case TYPE_CHAR :case TYPE_SHORT :case TYPE_INT : +case TYPE_INTBITFIELD :case TYPE_LONGLONG :case TYPE_ULONGLONG :case TYPE_LONG :
@@ -132,6 +133,26 @@ const argtype *thunk_convert(void *dst,case TYPE_INT : *(uint32_t *)dst =tswap32 (*(uint32_t *)src);break ; +case TYPE_INTBITFIELD : +#if defined(TARGET_I386 ) && defined(__powerpc__) +/* powerpc uses the MSB, whereas i386 uses the LSB +* to store the first bit in a field */ + { +unsigned char byte = *(uint8_t *)src; + *(uint8_t *)dst = ((byte >>7 ) &1 ) + | ((byte >>5 ) &2 ) + | ((byte >>3 ) &4 ) + | ((byte >>1 ) &8 ) + | ((byte <<1 ) &16 ) + | ((byte <<3 ) &32 ) + | ((byte <<5 ) &64 ) + | ((byte <<7 ) &128 ); +/* FIXME: implement for bitfields > 1 byte and other archs */ + } +#else + *(uint32_t *)dst =tswap32 (*(uint32_t *)src); +#endif +break ;case TYPE_LONGLONG :case TYPE_ULONGLONG : *(uint64_t *)dst =tswap64 (*(uint64_t *)src);
linux-user/ioctls.h +5 -0
@@ -300,3 +300,8 @@ IOCTL(VFAT_IOCTL_READDIR_BOTH, IOC_R, MK_PTR(MK_ARRAY(MK_STRUCT(STRUCT_dirent), 2)))IOCTL (VFAT_IOCTL_READDIR_SHORT ,IOC_R ,MK_PTR (MK_ARRAY (MK_STRUCT (STRUCT_dirent),2 ))) + +/* FIXME: including these on x86 / x86_64 breaks qemu-i386 */ +#ifdef __powerpc__ +#include "ioctls_alsa.h" +#endif
linux-user/ioctls_alsa.h new file +465 -0
465 lines not on this page · raw message
linux-user/ioctls_alsa_structs.h new file +1740 -0
1,740 lines not on this page · raw message
linux-user/syscall_defs.h +1 -0
@@ -1677,3 +1677,4 @@ struct target_sysinfo {#include "socket.h" #include "errno_defs.h" +#include "ioctls_alsa_structs.h"
linux-user/syscall_types.h +5 -0
@@ -79,3 +79,8 @@ STRUCT(count_info,STRUCT (mixer_info,MK_ARRAY (TYPE_CHAR ,16 ),MK_ARRAY (TYPE_CHAR ,32 ),TYPE_INT ,MK_ARRAY (TYPE_INT ,10 )) + +/* FIXME: including these on x86 / x86_64 breaks qemu-i386 */ +#ifdef __powerpc__ +#include "syscall_types_alsa.h" +#endif
linux-user/syscall_types_alsa.h new file +1337 -0
721 lines not on this page · raw message
The rest of this diff is not shown. View the raw message.
The rest of this diff is not shown. View the raw message.
#include <stdio.h>
struct a {
int x,y;
unsigned int a:1, b:1, c:1, d:1;
};unsigned char conv(unsigned char byte) {
// unsigned char byte = in;
return (byte >> 7) & 1
| (byte >> 5) & 2
| (byte >> 3) & 4
| (byte >> 1) & 8
| (byte << 1) & 16
| (byte << 3) & 32
| (byte << 5) & 64
| (byte << 7) & 128;
}int main() {
struct a a;
int i;
char *x;
memset(&a, 0, sizeof(struct a));
a.a = 0;
a.b = 1;
a.c = 0;
a.d = 0;
x = (char*)&a;
for(i=0; i<sizeof(struct a); i++) {
int j;
printf("%3d: %3hhd (%3hhd) ", i, x[i], conv(x[i]));
for(j=0; j<sizeof(char) * 8; j++)
printf("%d", (x[i] >> j) & 1);
printf("\n");
}
}The rest of this diff is not shown. View the raw message.
Part of the diff is not shown here. View the raw message.