From: Julian Seward Date: Tue, 26 Dec 2006 04:08:39 +0000 (+0000) Subject: Merge r6411 (usb ioctl handling) X-Git-Tag: svn/VALGRIND_3_2_2~47 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3252f362a60267e860c09f7a68c96f03e2d3d54f;p=thirdparty%2Fvalgrind.git Merge r6411 (usb ioctl handling) git-svn-id: svn://svn.valgrind.org/valgrind/branches/VALGRIND_3_2_BRANCH@6433 --- diff --git a/coregrind/m_syswrap/syswrap-generic.c b/coregrind/m_syswrap/syswrap-generic.c index 5801afce17..b380e5307f 100644 --- a/coregrind/m_syswrap/syswrap-generic.c +++ b/coregrind/m_syswrap/syswrap-generic.c @@ -4015,7 +4015,80 @@ PRE(sys_ioctl) case VKI_VT_UNLOCKSWITCH: break; - + case VKI_USBDEVFS_CONTROL: + if ( ARG3 ) { + struct vki_usbdevfs_ctrltransfer *vkuc = (struct vki_usbdevfs_ctrltransfer *)ARG3; + PRE_MEM_READ( "ioctl(USBDEVFS_CONTROL).bRequestType", (Addr)&vkuc->bRequestType, sizeof(vkuc->bRequestType)); + PRE_MEM_READ( "ioctl(USBDEVFS_CONTROL).bRequest", (Addr)&vkuc->bRequest, sizeof(vkuc->bRequest)); + PRE_MEM_READ( "ioctl(USBDEVFS_CONTROL).wValue", (Addr)&vkuc->wValue, sizeof(vkuc->wValue)); + PRE_MEM_READ( "ioctl(USBDEVFS_CONTROL).wIndex", (Addr)&vkuc->wIndex, sizeof(vkuc->wIndex)); + PRE_MEM_READ( "ioctl(USBDEVFS_CONTROL).wLength", (Addr)&vkuc->wLength, sizeof(vkuc->wLength)); + PRE_MEM_READ( "ioctl(USBDEVFS_CONTROL).timeout", (Addr)&vkuc->timeout, sizeof(vkuc->timeout)); + if (vkuc->bRequestType & 0x80) + PRE_MEM_WRITE( "ioctl(USBDEVFS_CONTROL).data", (Addr)vkuc->data, vkuc->wLength); + else + PRE_MEM_READ( "ioctl(USBDEVFS_CONTROL).data", (Addr)vkuc->data, vkuc->wLength); + } + break; + case VKI_USBDEVFS_BULK: + if ( ARG3 ) { + struct vki_usbdevfs_bulktransfer *vkub = (struct vki_usbdevfs_bulktransfer *)ARG3; + PRE_MEM_READ( "ioctl(USBDEVFS_BULK)", ARG3, sizeof(struct vki_usbdevfs_bulktransfer)); + if (vkub->ep & 0x80) + PRE_MEM_WRITE( "ioctl(USBDEVFS_BULK).data", (Addr)vkub->data, vkub->len); + else + PRE_MEM_READ( "ioctl(USBDEVFS_BULK).data", (Addr)vkub->data, vkub->len); + break; + } + case VKI_USBDEVFS_GETDRIVER: + if ( ARG3 ) { + struct vki_usbdevfs_getdriver *vkugd = (struct vki_usbdevfs_getdriver *) ARG3; + PRE_MEM_WRITE( "ioctl(USBDEVFS_GETDRIVER)", (Addr)&vkugd->driver, sizeof(vkugd->driver)); + break; + } + case VKI_USBDEVFS_SUBMITURB: + if ( ARG3 ) { + struct vki_usbdevfs_urb *vkuu = (struct vki_usbdevfs_urb *)ARG3; + + /* Not the whole struct needs to be initialized */ + PRE_MEM_READ( "ioctl(USBDEVFS_SUBMITURB).ep", (Addr)&vkuu->endpoint, sizeof(vkuu->endpoint)); + PRE_MEM_READ( "ioctl(USBDEVFS_SUBMITURB).type", (Addr)&vkuu->type, sizeof(vkuu->type)); + PRE_MEM_READ( "ioctl(USBDEVFS_SUBMITURB).flags", (Addr)&vkuu->flags, sizeof(vkuu->flags)); + PRE_MEM_READ( "ioctl(USBDEVFS_SUBMITURB).buffer", (Addr)&vkuu->buffer, sizeof(vkuu->buffer)); + PRE_MEM_READ( "ioctl(USBDEVFS_SUBMITURB).buffer_length", (Addr)&vkuu->buffer_length, sizeof(vkuu->buffer_length)); + PRE_MEM_READ( "ioctl(USBDEVFS_SUBMITURB).usercontext", (Addr)&vkuu->usercontext, sizeof(vkuu->usercontext)); + if (vkuu->endpoint & 0x80) + PRE_MEM_WRITE( "ioctl(USBDEVFS_URB).buffer", (Addr)vkuu->buffer, vkuu->buffer_length); + else + PRE_MEM_READ( "ioctl(USBDEVFS_URB).buffer", (Addr)vkuu->buffer, vkuu->buffer_length); + /* FIXME: Does not handle all cases this ioctl can do, ISOs are missing. */ + break; + } + case VKI_USBDEVFS_REAPURB: + case VKI_USBDEVFS_REAPURBNDELAY: + if ( ARG3 ) { + PRE_MEM_READ( "ioctl(USBDEVFS_SUBMITURB)", ARG3, sizeof(struct vki_usbdevfs_urb *)); + break; + } + case VKI_USBDEVFS_CONNECTINFO: + PRE_MEM_WRITE( "ioctl(USBDEVFS_CONNECTINFO)", ARG3, sizeof(struct vki_usbdevfs_connectinfo)); + break; + case VKI_USBDEVFS_IOCTL: + if ( ARG3 ) { + struct vki_usbdevfs_ioctl *vkui = (struct vki_usbdevfs_ioctl *)ARG3; + UInt dir2, size2; + PRE_MEM_READ("ioctl(USBDEVFS_IOCTL)", (Addr)vkui, sizeof(struct vki_usbdevfs_ioctl)); + dir2 = _VKI_IOC_DIR(vkui->ioctl_code); + size2 = _VKI_IOC_SIZE(vkui->ioctl_code); + if (size2 > 0) { + if (dir2 & _VKI_IOC_WRITE) + PRE_MEM_READ("ioctl(USBDEVFS_IOCTL).dataWrite", (Addr)vkui->data, size2); + else if (dir2 & _VKI_IOC_READ) + PRE_MEM_WRITE("ioctl(USBDEVFS_IOCTL).dataRead", (Addr)vkui->data, size2); + } + } + break; + /* We don't have any specific information on it, so try to do something reasonable based on direction and size bits. The encoding scheme is described in @@ -4676,7 +4749,53 @@ POST(sys_ioctl) case VKI_VT_LOCKSWITCH: case VKI_VT_UNLOCKSWITCH: break; - + + case VKI_USBDEVFS_CONTROL: + if ( ARG3 ) { + struct vki_usbdevfs_ctrltransfer *vkuc = (struct vki_usbdevfs_ctrltransfer *)ARG3; + if (vkuc->bRequestType & 0x80) + POST_MEM_WRITE((Addr)vkuc->data, RES); + break; + } + case VKI_USBDEVFS_BULK: + if ( ARG3 ) { + struct vki_usbdevfs_bulktransfer *vkub = (struct vki_usbdevfs_bulktransfer *)ARG3; + if (vkub->ep & 0x80) + POST_MEM_WRITE((Addr)vkub->data, RES); + break; + } + case VKI_USBDEVFS_GETDRIVER: + if ( ARG3 ) { + struct vki_usbdevfs_getdriver *vkugd = (struct vki_usbdevfs_getdriver *)ARG3; + POST_MEM_WRITE((Addr)&vkugd->driver, sizeof(vkugd->driver)); + break; + } + case VKI_USBDEVFS_REAPURB: + case VKI_USBDEVFS_REAPURBNDELAY: + if ( ARG3 ) { + struct vki_usbdevfs_urb **vkuu = (struct vki_usbdevfs_urb**)ARG3; + if (!*vkuu) + break; + POST_MEM_WRITE((Addr) &((*vkuu)->status),sizeof((*vkuu)->status)); + if ((*vkuu)->endpoint & 0x80) + POST_MEM_WRITE((Addr)(*vkuu)->buffer, (*vkuu)->actual_length); + break; + } + case VKI_USBDEVFS_CONNECTINFO: + POST_MEM_WRITE(ARG3, sizeof(struct vki_usbdevfs_connectinfo)); + break; + case VKI_USBDEVFS_IOCTL: + if ( ARG3 ) { + struct vki_usbdevfs_ioctl *vkui = (struct vki_usbdevfs_ioctl *)ARG3; + UInt dir2, size2; + dir2 = _VKI_IOC_DIR(vkui->ioctl_code); + size2 = _VKI_IOC_SIZE(vkui->ioctl_code); + if (size2 > 0) { + if (dir2 & _VKI_IOC_READ) + POST_MEM_WRITE((Addr)vkui->data, size2); + } + } + break; /* We don't have any specific information on it, so try to do something reasonable based on direction and diff --git a/include/vki-linux.h b/include/vki-linux.h index 9de6eb3715..46c41d6bdd 100644 --- a/include/vki-linux.h +++ b/include/vki-linux.h @@ -2224,6 +2224,77 @@ struct vki_vt_consize { # define VKI_PR_ENDIAN_LITTLE 1 /* True little endian mode */ # define VKI_PR_ENDIAN_PPC_LITTLE 2 /* "PowerPC" pseudo little endian */ +//---------------------------------------------------------------------- +// From linux-2.6.19/include/linux/usbdevice_fs.h +//---------------------------------------------------------------------- + +struct vki_usbdevfs_ctrltransfer { + __vki_u8 bRequestType; + __vki_u8 bRequest; + __vki_u16 wValue; + __vki_u16 wIndex; + __vki_u16 wLength; + __vki_u32 timeout; /* in milliseconds */ + void __user *data; +}; + +struct vki_usbdevfs_bulktransfer { + unsigned int ep; + unsigned int len; + unsigned int timeout; /* in milliseconds */ + void __user *data; +}; + +#define VKI_USBDEVFS_MAXDRIVERNAME 255 + +struct vki_usbdevfs_getdriver { + unsigned int interface; + char driver[VKI_USBDEVFS_MAXDRIVERNAME + 1]; +}; + +struct vki_usbdevfs_connectinfo { + unsigned int devnum; + unsigned char slow; +}; + +struct vki_usbdevfs_iso_packet_desc { + unsigned int length; + unsigned int actual_length; + unsigned int status; +}; + +struct vki_usbdevfs_urb { + unsigned char type; + unsigned char endpoint; + int status; + unsigned int flags; + void __user *buffer; + int buffer_length; + int actual_length; + int start_frame; + int number_of_packets; + int error_count; + unsigned int signr; /* signal to be sent on error, -1 if none should be sent */ + void *usercontext; + struct vki_usbdevfs_iso_packet_desc iso_frame_desc[0]; +}; + +struct vki_usbdevfs_ioctl { + int ifno; /* interface 0..N ; negative numbers reserved */ + int ioctl_code; /* MUST encode size + direction of data so the + * macros in give correct values */ + void __user *data; /* param buffer (in, or out) */ +}; + +#define VKI_USBDEVFS_CONTROL _VKI_IOWR('U', 0, struct vki_usbdevfs_ctrltransfer) +#define VKI_USBDEVFS_BULK _VKI_IOWR('U', 2, struct vki_usbdevfs_bulktransfer) +#define VKI_USBDEVFS_GETDRIVER _VKI_IOW('U', 8, struct vki_usbdevfs_getdriver) +#define VKI_USBDEVFS_SUBMITURB _VKI_IOR('U', 10, struct vki_usbdevfs_urb) +#define VKI_USBDEVFS_REAPURB _VKI_IOW('U', 12, void *) +#define VKI_USBDEVFS_REAPURBNDELAY _VKI_IOW('U', 13, void *) +#define VKI_USBDEVFS_CONNECTINFO _VKI_IOW('U', 17, struct vki_usbdevfs_connectinfo) +#define VKI_USBDEVFS_IOCTL _VKI_IOWR('U', 18, struct vki_usbdevfs_ioctl) + #endif // __VKI_LINUX_H /*--------------------------------------------------------------------*/