Alexandre Julliard : server: Implement read and write requests for device files.
Alexandre Julliard
julliard at wine.codeweavers.com
Wed May 6 09:29:04 CDT 2015
Module: wine
Branch: master
Commit: faa1db4d13fe3d87075b47f3987d38de3bf9b505
URL: http://source.winehq.org/git/wine.git/?a=commit;h=faa1db4d13fe3d87075b47f3987d38de3bf9b505
Author: Alexandre Julliard <julliard at winehq.org>
Date: Tue May 5 12:51:11 2015 +0900
server: Implement read and write requests for device files.
---
server/device.c | 95 +++++++++++++++++++++++++++++++++++++++++----------------
1 file changed, 68 insertions(+), 27 deletions(-)
diff --git a/server/device.c b/server/device.c
index 9301f31..353b9a5 100644
--- a/server/device.c
+++ b/server/device.c
@@ -128,6 +128,10 @@ static void device_destroy( struct object *obj );
static struct object *device_open_file( struct object *obj, unsigned int access,
unsigned int sharing, unsigned int options );
static enum server_fd_type device_get_fd_type( struct fd *fd );
+static obj_handle_t device_read( struct fd *fd, const async_data_t *async_data, int blocking,
+ file_pos_t pos );
+static obj_handle_t device_write( struct fd *fd, const async_data_t *async_data, int blocking,
+ file_pos_t pos, data_size_t *written );
static obj_handle_t device_ioctl( struct fd *fd, ioctl_code_t code, const async_data_t *async_data,
int blocking );
@@ -156,8 +160,8 @@ static const struct fd_ops device_fd_ops =
default_fd_get_poll_events, /* get_poll_events */
default_poll_event, /* poll_event */
device_get_fd_type, /* get_fd_type */
- no_fd_read, /* read */
- no_fd_write, /* write */
+ device_read, /* read */
+ device_write, /* write */
no_fd_flush, /* flush */
device_ioctl, /* ioctl */
default_fd_queue_async, /* queue_async */
@@ -199,6 +203,12 @@ static struct irp_call *create_irp( struct device *device, unsigned int type, co
{
struct irp_call *irp;
+ if (!device->manager) /* it has been deleted */
+ {
+ set_error( STATUS_FILE_DELETED );
+ return NULL;
+ }
+
if ((irp = alloc_object( &irp_call_ops )))
{
irp->device = (struct device *)grab_object( device );
@@ -315,48 +325,79 @@ static struct irp_call *find_irp_call( struct device *device, struct thread *thr
return NULL;
}
-static obj_handle_t device_ioctl( struct fd *fd, ioctl_code_t code, const async_data_t *async_data,
- int blocking )
+/* queue an irp to the device */
+static obj_handle_t queue_irp( struct device *device, struct irp_call *irp,
+ const async_data_t *async_data, int blocking )
{
- struct device *device = get_fd_user( fd );
- struct irp_call *irp;
obj_handle_t handle = 0;
- if (!device->manager) /* it has been deleted */
- {
- set_error( STATUS_FILE_DELETED );
- return 0;
- }
-
- if (!(irp = create_irp( device, IRP_MJ_DEVICE_CONTROL, get_req_data(), get_req_data_size(),
- get_reply_max_size() )))
- return 0;
-
- irp->code = code;
- irp->thread = (struct thread *)grab_object( current );
- irp->user_arg = async_data->arg;
-
- if (blocking && !(handle = alloc_handle( current->process, irp, SYNCHRONIZE, 0 )))
- {
- release_object( irp );
- return 0;
- }
+ if (blocking && !(handle = alloc_handle( current->process, irp, SYNCHRONIZE, 0 ))) return 0;
if (!(irp->async = fd_queue_async( device->fd, async_data, ASYNC_TYPE_WAIT )))
{
if (handle) close_handle( current->process, handle );
- release_object( irp );
return 0;
}
+ irp->thread = (struct thread *)grab_object( current );
+ irp->user_arg = async_data->arg;
+ grab_object( irp ); /* grab reference for queued irp */
+
list_add_tail( &device->requests, &irp->dev_entry );
list_add_tail( &device->manager->requests, &irp->mgr_entry );
if (list_head( &device->manager->requests ) == &irp->mgr_entry) /* first one */
wake_up( &device->manager->obj, 0 );
- /* don't release irp since it is now queued in the device */
set_error( STATUS_PENDING );
return handle;
}
+static obj_handle_t device_read( struct fd *fd, const async_data_t *async_data, int blocking,
+ file_pos_t pos )
+{
+ struct device *device = get_fd_user( fd );
+ struct irp_call *irp;
+ obj_handle_t handle;
+
+ irp = create_irp( device, IRP_MJ_READ, NULL, 0, get_reply_max_size() );
+ if (!irp) return 0;
+
+ handle = queue_irp( device, irp, async_data, blocking );
+ release_object( irp );
+ return handle;
+}
+
+static obj_handle_t device_write( struct fd *fd, const async_data_t *async_data, int blocking,
+ file_pos_t pos, data_size_t *written )
+{
+ struct device *device = get_fd_user( fd );
+ struct irp_call *irp;
+ obj_handle_t handle;
+
+ irp = create_irp( device, IRP_MJ_WRITE, get_req_data(), get_req_data_size(), 0 );
+ if (!irp) return 0;
+
+ handle = queue_irp( device, irp, async_data, blocking );
+ release_object( irp );
+ return handle;
+}
+
+static obj_handle_t device_ioctl( struct fd *fd, ioctl_code_t code, const async_data_t *async_data,
+ int blocking )
+{
+ struct device *device = get_fd_user( fd );
+ struct irp_call *irp;
+ obj_handle_t handle;
+
+ irp = create_irp( device, IRP_MJ_DEVICE_CONTROL, get_req_data(), get_req_data_size(),
+ get_reply_max_size() );
+ if (!irp) return 0;
+
+ irp->code = code;
+
+ handle = queue_irp( device, irp, async_data, blocking );
+ release_object( irp );
+ return handle;
+}
+
static struct device *create_device( struct directory *root, const struct unicode_str *name,
struct device_manager *manager, unsigned int attr )
{
More information about the wine-cvs
mailing list