From 6ec11a2b26edbb82d15d98f63322b66a88a5efa0 Mon Sep 17 00:00:00 2001 From: Benjamin Berg Date: Wed, 3 Jul 2019 23:51:58 +0200 Subject: [PATCH] cocci: Add spatch/coccinelle patches for driver porting This is an impartial set of transformations to help port the drivers to the new interfaces. --- cocci/00-misc-cleanups.cocci | 78 ++++++ cocci/01-endpoint.cocci | 8 + cocci/02-type-renames.cocci | 64 +++++ cocci/03-function-renames.cocci | 80 ++++++ cocci/04-misc-renames.cocci | 29 +++ cocci/05-libusb-1.cocci | 118 +++++++++ cocci/06-libusb-callback-1.cocci | 344 +++++++++++++++++++++++++ cocci/07-libusb-fill.cocci | 163 ++++++++++++ cocci/08-ssm.cocci | 20 ++ cocci/10-driver.cocci | 386 ++++++++++++++++++++++++++++ cocci/99-insert-checking-code.cocci | 38 +++ cocci/all.cocci | 19 ++ cocci/apply-all | 9 + 13 files changed, 1356 insertions(+) create mode 100644 cocci/00-misc-cleanups.cocci create mode 100644 cocci/01-endpoint.cocci create mode 100644 cocci/02-type-renames.cocci create mode 100644 cocci/03-function-renames.cocci create mode 100644 cocci/04-misc-renames.cocci create mode 100644 cocci/05-libusb-1.cocci create mode 100644 cocci/06-libusb-callback-1.cocci create mode 100644 cocci/07-libusb-fill.cocci create mode 100644 cocci/08-ssm.cocci create mode 100644 cocci/10-driver.cocci create mode 100644 cocci/99-insert-checking-code.cocci create mode 100644 cocci/all.cocci create mode 100755 cocci/apply-all diff --git a/cocci/00-misc-cleanups.cocci b/cocci/00-misc-cleanups.cocci new file mode 100644 index 0000000..dfaba64 --- /dev/null +++ b/cocci/00-misc-cleanups.cocci @@ -0,0 +1,78 @@ +// Remove USB device reset, lets hope that we do not need this. +// If we do, maybe do it elsewhere? +@@ +identifier r; +@@ +- r = libusb_reset_device(...); +- if (r != 0) { ... } + +// Functions that have uneccessary returns (i.e. error cannot happen after refactoring) +// NOTE: Make sure that these function are fine to modify in *all* drivers! +@ prior_int_func @ +identifier func =~ "capture_chunk_async|alksdjflkajsfd"; +expression res, res2; +@@ +-int func ++void func + (...) +{ + <... +- return res2; ++ res2; + ...> +- return res; ++ res; +} + +@@ +identifier prior_int_func.func; +identifier res; +@@ +-res = func ++func + (...); +( +-if (res < 0) { ... } +| +-if (res != 0) { ... } +) + +// Remove useless checks of fpi_timeout_add return values +@@ +expression a1, a2, a3, a4; +@@ +-if (fpi_timeout_add(a1, a2, a3, a4) == NULL) { ... } ++fpi_timeout_add(a1, a2, a3, a4); + +@@ +identifier timeout; +expression a1, a2, a3, a4; +@@ +timeout = fpi_timeout_add(a1, a2, a3, a4); +-if (timeout == NULL) { ... } + + +// The VFS5011 driver has some stupid "radiation detected" logic, that should be asserts +@@ +expression expr; +@@ +-if ((expr)) { +- ... +- fp_err("Radiation detected!"); +- ... +-} ++g_assert(!expr); + + +// A number of drivers call both fpi_imgdev_session_error *and* fpi_ssm_mark_failed. +// While this worked fine, it is plain wrong and considerably complicates memory +// management of the errors. +// Remove this duplication +@@ +expression dev; +expression ssm; +expression error; +@@ +- fpi_imgdev_session_error(dev, error); + fpi_ssm_mark_failed(ssm, error); + diff --git a/cocci/01-endpoint.cocci b/cocci/01-endpoint.cocci new file mode 100644 index 0000000..d350720 --- /dev/null +++ b/cocci/01-endpoint.cocci @@ -0,0 +1,8 @@ +@@ +@@ +- LIBUSB_ENDPOINT_IN ++ FP_USB_ENDPOINT_IN +@@ +@@ +- LIBUSB_ENDPOINT_OUT ++ FP_USB_ENDPOINT_OUT diff --git a/cocci/02-type-renames.cocci b/cocci/02-type-renames.cocci new file mode 100644 index 0000000..e37fc92 --- /dev/null +++ b/cocci/02-type-renames.cocci @@ -0,0 +1,64 @@ +@ fp_img_dev @ +typedef FpImageDevice; +@@ +-struct fp_img_dev ++FpImageDevice + +@ FpImageDevice_cast @ +typedef FpImageDevice; +expression dev; +@@ +-(FpImageDevice*) dev ++FP_IMAGE_DEVICE (dev) + +@ fp_dev @ +typedef FpDevice; +@@ +-struct fp_dev ++FpDevice + +@ FpDevice_cast @ +typedef FpDevice; +expression dev; +@@ +-(FpDevice*) dev ++FP_DEVICE (dev) + +@ FP_DEV_cast @ +expression dev; +@@ +- FP_DEV (dev) ++ FP_DEVICE (dev) + +@ FP_IMG_DEV_cast @ +expression dev; +@@ +- FP_IMG_DEV (dev) ++ FP_IMAGE_DEVICE (dev) + +@ fpi_ssm @ +typedef fpi_ssm; +typedef FpSsm; +@@ +-fpi_ssm ++FpSsm + +@ fp_img @ +typedef FpImage; +@@ +-struct fp_img ++FpImage + +@ libusb_transfer @ +typedef FpUsbTransfer; +@@ +-struct libusb_transfer ++FpUsbTransfer + +@ libusb_device_handle @ +typedef libusb_device_handle; +typedef GUsbDevice; +@@ +-libusb_device_handle ++GUsbDevice + diff --git a/cocci/03-function-renames.cocci b/cocci/03-function-renames.cocci new file mode 100644 index 0000000..cd26152 --- /dev/null +++ b/cocci/03-function-renames.cocci @@ -0,0 +1,80 @@ +@@ +expression w; +expression h; +expression status; +expression dev; +expression a1, a2, a3; +@@ +( +-fpi_img_new(w * h) ++fp_image_new(w, h) +| +-fpi_ssm_new ++fp_ssm_new +| +-fpi_ssm_free ++fp_ssm_free +| +-fpi_ssm_start ++fp_ssm_start +| +-fpi_ssm_start_subsm ++fp_ssm_start_subsm +| +-fpi_ssm_next_state ++fp_ssm_next_state +| +-fpi_ssm_jump_to_state ++fp_ssm_jump_to_state +| +-fpi_ssm_mark_completed ++fp_ssm_mark_completed +| +-fpi_ssm_get_user_data ++fp_ssm_get_user_data +| +-fpi_ssm_get_cur_state ++fp_ssm_get_cur_state +| +-fpi_dev_get_usb_dev ++_fp_device_get_usb_device +| +// HACK: We just insert an error return here! +-fpi_imgdev_close_complete(dev) ++_fp_image_device_close_complete(dev, error) +| +-fpi_imgdev_open_complete(dev, 0) ++_fp_image_device_open_complete(dev, NULL) +| +-fpi_imgdev_activate_complete(dev, 0) ++_fp_image_device_activate_complete(dev, NULL) +| +-fpi_imgdev_deactivate_complete(dev) ++_fp_image_device_deactivate_complete(dev, NULL) +| +-fpi_imgdev_report_finger_status(dev, status) ++_fp_image_device_report_finger_status(dev, status) +| +-fpi_imgdev_image_captured(dev, a1) ++_fp_image_device_image_captured(dev, a1) +| +-fpi_imgdev_abort_scan ++_fp_image_device_retry_scan +| +-fpi_std_sq_dev ++_fp_std_sq_dev +| +-fpi_mean_sq_diff_norm ++_fp_mean_sq_diff_norm +| +-fpi_timeout_add(a1, a2, dev, a3) ++_fp_device_add_timeout(dev, a1, a2, a3) +) + +// Some can be nested +@@ +@@ +( +-fpi_ssm_next_state_timeout_cb ++fp_ssm_next_state_timeout_cb +) diff --git a/cocci/04-misc-renames.cocci b/cocci/04-misc-renames.cocci new file mode 100644 index 0000000..8bf40a6 --- /dev/null +++ b/cocci/04-misc-renames.cocci @@ -0,0 +1,29 @@ +@@ +typedef FpImageDeviceState; +@@ +( +-FP_IMG_COLORS_INVERTED ++FP_IMAGE_COLORS_INVERTED +| +-FP_IMG_H_FLIPPED ++FP_IMAGE_H_FLIPPED +| +-FP_IMG_V_FLIPPED ++FP_IMAGE_V_FLIPPED +| +-FP_VERIFY_RETRY_TOO_SHORT ++FP_DEVICE_RETRY_TOO_SHORT +| +-FP_VERIFY_RETRY_CENTER_FINGER ++FP_DEVICE_RETRY_CENTER_FINGER +| +-FP_VERIFY_RETRY ++FP_DEVICE_RETRY +) + +@@ +@@ +( +-enum fp_imgdev_state ++FpImageDeviceState +) diff --git a/cocci/05-libusb-1.cocci b/cocci/05-libusb-1.cocci new file mode 100644 index 0000000..0b6cc48 --- /dev/null +++ b/cocci/05-libusb-1.cocci @@ -0,0 +1,118 @@ + +@ dev_func @ +identifier dev; +identifier func; +@@ +func(..., FpDevice *dev, ...) +{ + ... +} + +@ imgdev_func @ +identifier dev; +identifier func; +@@ +func(..., FpImageDevice *dev, ...) +{ + ... +} + +@ self_func extends driver @ +identifier self; +identifier func; +@@ +func(..., driver_cls *self, ...) +{ + ... +} + +@ transfer_func_imgdev @ +typedef FpUsbTransfer; +identifier imgdev_func.func; +identifier imgdev_func.dev; +identifier transfer; +@@ +func (...) +{ +<... +( +-transfer = fpi_usb_alloc(); ++transfer = fp_usb_transfer_new(FP_DEVICE (dev)); +| +-FpUsbTransfer *transfer = fpi_usb_alloc(); ++FpUsbTransfer *transfer = fp_usb_transfer_new(FP_DEVICE (dev)); +) +...> +} + + +@ transfer_func_dev @ +typedef FpUsbTransfer; +identifier dev_func.func; +identifier dev_func.dev; +identifier transfer; +@@ +func (...) +{ +<... +( +-transfer = fpi_usb_alloc(); ++transfer = fp_usb_transfer_new(dev); +| +-FpUsbTransfer *transfer = fpi_usb_alloc(); ++FpUsbTransfer *transfer = fp_usb_transfer_new(dev); +) +...> +} + +@ transfer_func_self @ +typedef FpUsbTransfer; +identifier self_func.func; +identifier self_func.self; +expression transfer; +@@ +func (...) +{ +<... +-transfer = fpi_usb_alloc(); ++transfer = fp_usb_transfer_new(FP_DEVICE (self)); +...> +} + +// None of the release interface calls had error handling ... +@ extends driver @ +expression usb_dev; +expression interface; +@@ +dev_close(...) +{ ++ GError *error = NULL; +... +-libusb_release_interface(usb_dev, interface); ++g_usb_device_release_interface(usb_dev, interface, 0, &error); +... +} + +@ extends driver @ +expression usb_dev; +expression interface; +identifier imgdev; +identifier r; +@@ +dev_open (..., FpImageDevice *imgdev, ...) +{ ++ GError *error = NULL; +... +-r = libusb_claim_interface(usb_dev, interface); ++if (!g_usb_device_claim_interface(usb_dev, interface, 0, &error)) { ++ _fp_image_device_open_complete (imgdev, error); ++ return; ++ } +( +-if (r != 0) { ... } +| +-if (r < 0) { ... } +) +... +} + diff --git a/cocci/06-libusb-callback-1.cocci b/cocci/06-libusb-callback-1.cocci new file mode 100644 index 0000000..643163a --- /dev/null +++ b/cocci/06-libusb-callback-1.cocci @@ -0,0 +1,344 @@ +@ usb_transfer_cb @ +typedef FpUsbTransfer; +typedef FpSsm; +identifier func; +identifier transfer; +identifier dev; +identifier ssm; +@@ +( +-void func(FpUsbTransfer *transfer) ++void func(FpUsbTransfer *transfer, ++ FpDevice *device, ++ gpointer user_data, ++ GError *error) +{ +... +} +| +// this is weird, one function in uru4000 didn't get the types +// converted by earlier rules. But, this does not seem to work either. +-void func(\(FpUsbTransfer*\|struct libusb_transfer*\) transfer, +- \(FpDevice*\|struct fp_dev*\) dev, +- \(FpSsm*\|fpi_ssm*\) ssm, +- void* user_data) ++void func(FpUsbTransfer *transfer, ++ FpDevice *dev, ++ gpointer user_data, ++ GError *error) +{ ++ FpSsm *ssm = transfer->ssm; +... +} +) + + +@ errors_generic_1 @ +identifier usb_transfer_cb.func; +identifier usb_transfer_cb.transfer; +@@ +func(...) +{ + <... +( +- (transfer->status != LIBUSB_TRANSFER_COMPLETED) ++ error +| +- (transfer->status == LIBUSB_TRANSFER_COMPLETED) ++ !error +| +- (transfer->status == LIBUSB_TRANSFER_TIMED_OUT) ++ g_error_matches (error, G_USB_DEVICE_ERROR, G_USB_DEVICE_ERROR_TIMED_OUT) +) + ...> +} + + +@ errors_1 @ +identifier usb_transfer_cb.func; +identifier usb_transfer_cb.transfer; +expression ssm; +statement S; +@@ +func(...) +{ + <... + if (error) { +( + ... +- fpi_ssm_mark_failed (ssm, ...) ++ fp_ssm_mark_failed (ssm, error) + ... +| + ... +- fpi_imgdev_session_error (...) ++ _fp_image_device_session_error (FP_IMAGE_DEVICE (device), error) + ... +) + } + ...> +} + +@ errors_1_alt @ +identifier usb_transfer_cb.func; +identifier usb_transfer_cb.transfer; +expression ssm; +statement S; +@@ +func(...) +{ + <... + if (!error) { ... } + else { +( + ... +- fpi_ssm_mark_failed (ssm, ...) ++ fp_ssm_mark_failed (ssm, error) + ... +| + ... +- fpi_imgdev_session_error (...) ++ _fp_image_device_session_error (FP_IMAGE_DEVICE (device), error) + ... +) + } + ...> +} + +@ errors_2 @ +identifier usb_transfer_cb.func; +identifier usb_transfer_cb.transfer; +expression ssm; +@@ +func(...) +{ + <... + if (transfer->length != transfer->actual_length) { ++ _Pragma("GCC warning \"Driver should probably set short_is_error instead!\""); + ... +( +- fpi_ssm_mark_failed (ssm, ...); ++ fp_ssm_mark_failed (ssm, g_error_new (G_USB_DEVICE_ERROR, ++ G_USB_DEVICE_ERROR_IO, ++ "Short USB transfer!")); +| +- fpi_imgdev_session_error (...); ++ _fp_image_device_session_error (FP_IMAGE_DEVICE (device), ++ g_error_new (G_USB_DEVICE_ERROR, ++ G_USB_DEVICE_ERROR_IO, ++ "Short USB transfer!")); +) + ... + } + ...> +} + +@ not_useful_error_prints @ +identifier usb_transfer_cb.func; +@@ +func(...) +{ + <... +- fp_err (...); + ... +( + fp_ssm_mark_failed (...); +| + _fp_image_device_session_error (...); +) + ...> +} + +@ error_or_wrong_length @ +identifier usb_transfer_cb.func; +identifier usb_transfer_cb.transfer; +expression ssm; +@@ +func(...) +{ + <... +- if (error || (transfer->length != transfer->actual_length)) ++ if (error) + { ++ _Pragma("GCC warning \"Driver needs to set short_is_error for this branch to be taken!\""); + <... +( +- fpi_ssm_mark_failed (ssm, ...); ++ fp_ssm_mark_failed (ssm, error); +| +- fpi_imgdev_session_error (...); ++ _fp_image_device_session_error (FP_IMAGE_DEVICE (device), error); +) + ...> + } + ...> +} + +@ error_or_wrong_length_2 @ +identifier usb_transfer_cb.func; +identifier usb_transfer_cb.transfer; +expression ssm; +@@ +func(...) +{ + <... +- if (!error && (transfer->length == transfer->actual_length)) ++ if (!error) + { ... } + else { ++ _Pragma("GCC warning \"Driver needs to set short_is_error for this branch to be taken!\""); + <... +( +- fpi_ssm_mark_failed (ssm, ...); ++ fp_ssm_mark_failed (ssm, error); +| +- fpi_imgdev_session_error (...); ++ _fp_image_device_session_error (FP_IMAGE_DEVICE (device), error); +) + ...> + } + ...> +} + + +@@ +identifier usb_transfer_cb.func; +identifier usb_transfer_cb.transfer; +identifier out; +@@ +func(...) +{ +<... +- goto out; ++ return; +...> +-out: +( +- g_free(transfer->buffer); +| +) +- libusb_free_transfer (transfer); +} + +@@ +identifier usb_transfer_cb.func; +identifier usb_transfer_cb.transfer; +@@ +func(...) +{ + <... +( +- g_free(transfer->buffer); +| +) +- libusb_free_transfer (transfer); + ... + return; + ...> +} + + +@@ +identifier usb_transfer_cb.func; +identifier usb_transfer_cb.transfer; +@@ +func(...) +{ + <... +- transfer->user_data ++ user_data + ...> +} + +@@ +typedef gint; +identifier usb_transfer_cb.func; +identifier usb_transfer_cb.transfer; +@@ +func(...) +{ +<... +( + fp_dbg +| + fp_warn +| + fp_err +) + (..., +- transfer->length ++ (gint) transfer->length + , ...); +...> +} + +@@ +typedef gint; +identifier usb_transfer_cb.func; +identifier usb_transfer_cb.transfer; +@@ +func(...) +{ +<... +( + fp_dbg +| + fp_warn +| + fp_err +) + (..., +- transfer->actual_length ++ (gint) transfer->actual_length + , ...); +...> +} + +@@ +identifier usb_transfer_cb.func; +identifier usb_transfer_cb.transfer; +identifier ssm_var; +gpointer user_data; +@@ +func(...) +{ + ... +( +- FpSsm *ssm_var = (FpSsm*) user_data; +| +- FpSsm *ssm_var = user_data; +) + <... +- ssm_var ++ transfer->ssm + ...> +} + +// A lot of drivers abuse the SSM user_data for the driver +// Convert FpImageDevice usage to simple cast +@@ +identifier usb_transfer_cb.func; +identifier dev; +@@ +func(...) +{ +-FpImageDevice *dev = ...; ++FpImageDevice *dev = FP_IMAGE_DEVICE (device); +... +} + +// A lot of drivers abuse the SSM user_data for the driver +// Remove FpDevice getter and use argument +@@ +identifier usb_transfer_cb.func; +identifier arg; +identifier dev; +@@ +func(..., FpDevice *arg, ...) +{ +-FpDevice *dev = ...; +<... +-dev ++arg +...> +} diff --git a/cocci/07-libusb-fill.cocci b/cocci/07-libusb-fill.cocci new file mode 100644 index 0000000..04fca26 --- /dev/null +++ b/cocci/07-libusb-fill.cocci @@ -0,0 +1,163 @@ +/////////////////////////////////////////////////////////////////////////// +// bulk transfers +@@ +typedef FpUsbTransfer; +expression transfer; +expression usb_dev; +expression endpoint; +expression data; +expression size; +expression cb; +expression user_data; +expression timeout; +identifier ret; +@@ +- libusb_fill_bulk_transfer(transfer, usb_dev, endpoint, data, size, cb, user_data, timeout); ++ fp_usb_transfer_fill_bulk_full(transfer, endpoint, data, size, NULL); ++ fp_usb_transfer_submit(transfer, timeout, NULL, cb, user_data); ++ fp_usb_transfer_unref(transfer); +( +- ret = libusb_submit_transfer(transfer); + ... +( +- if (ret < 0) { ... } +| +- if (ret != 0) { ... } +| +) +| +- if (libusb_submit_transfer(transfer)) { ... } +| +- if (libusb_submit_transfer(transfer) < 0) { ... } +| +- libusb_submit_transfer(transfer); +) + +/////////////////////////////////////////////////////////////////////////// +// bulk transfers +@@ +typedef FpUsbTransfer; +expression transfer; +expression dev; +expression transfer_ssm; +expression endpoint; +expression data; +expression size; +expression cb; +expression user_data; +expression timeout; +expression storage; +identifier ret; +@@ +- transfer = fpi_usb_fill_bulk_transfer(dev, transfer_ssm, endpoint, data, size, cb, user_data, timeout); ++ transfer = fp_usb_transfer_new (dev); ++ transfer->ssm = transfer_ssm; ++ fp_usb_transfer_fill_bulk_full(transfer, endpoint, data, size, NULL); ++ fp_usb_transfer_submit(transfer, timeout, NULL, cb, user_data); ++ fp_usb_transfer_unref(transfer); +( + storage = transfer; +| +) +( +- ret = fpi_usb_submit_transfer(transfer); + ... +( +- if (ret < 0) { ... } +| +- if (ret != 0) { ... } +| +) +| +- if (fpi_usb_submit_transfer(transfer)) { ... } +| +- if (fpi_usb_submit_transfer(transfer) < 0) { ... } +| +- fpi_usb_submit_transfer(transfer); +) + +// The following only happens due to some prior simplifications we did +@@ +typedef FpUsbTransfer; +expression transfer; +expression usb_dev; +expression endpoint; +expression data; +expression size; +expression cb; +expression user_data; +expression timeout; +identifier ret; +@@ +- libusb_fill_bulk_transfer(transfer, usb_dev, endpoint, data, size, cb, user_data, timeout); +- libusb_submit_transfer(transfer); ++ fp_usb_transfer_fill_bulk_full(transfer, endpoint, data, size, NULL); ++ fp_usb_transfer_submit(transfer, timeout, NULL, cb, user_data); ++ fp_usb_transfer_unref(transfer); + + +/////////////////////////////////////////////////////////////////////////// +// control transfers +@@ +typedef FpUsbTransfer; +expression timeout; +expression direction; +expression request_type; +expression recipient; +expression request; +expression value; +expression index; +expression length; +expression callback; +expression user_data; +expression usb_dev; +identifier ret; +@@ +( +- data = g_malloc(LIBUSB_CONTROL_SETUP_SIZE) +| +- data = g_malloc(LIBUSB_CONTROL_SETUP_SIZE + ...) +| +- data = g_malloc0(LIBUSB_CONTROL_SETUP_SIZE) +| +- data = g_malloc0(LIBUSB_CONTROL_SETUP_SIZE + ...) +) +- ; ++ _Pragma("GCC warning \"control transfer filling is a mess due to automatic translation\""); ++ fp_usb_transfer_fill_control(transfer, !((request_type) & 0x80), ((request_type) >> 5) & 0x3, (request_type) & 0x1f, request, value, index, length); ++ data = transfer->buffer; ++ fp_usb_transfer_submit(transfer, timeout, NULL, callback, user_data); ++ fp_usb_transfer_unref(transfer); + ... +- libusb_fill_control_setup(data, request_type, request, value, index, length); +- libusb_fill_control_transfer(transfer, usb_dev, data, callback, user_data, timeout); + <... +- LIBUSB_CONTROL_SETUP_SIZE + ...> +- ret = libusb_submit_transfer(transfer); +( +- if (ret < 0) { ... } +| +) + + +/////////////////////////////////////////////////////////////////////////// +// We have a field in the transfer just for a state machine, use that +// We also later modify all similar code on the callback side to use that field +// instead. +@@ +expression transfer; +expression timeout; +expression cb; +@@ ++ transfer->ssm = ssm; +- fp_usb_transfer_submit(transfer, timeout, NULL, cb, ssm); ++ fp_usb_transfer_submit(transfer, timeout, NULL, cb, NULL); +@@ +expression transfer; +expression timeout; +expression cb; +@@ +- fp_usb_transfer_submit(transfer, timeout, NULL, cb, dev); ++ fp_usb_transfer_submit(transfer, timeout, NULL, cb, NULL); + diff --git a/cocci/08-ssm.cocci b/cocci/08-ssm.cocci new file mode 100644 index 0000000..0039779 --- /dev/null +++ b/cocci/08-ssm.cocci @@ -0,0 +1,20 @@ +@ ssm_callbacks @ +identifier ssm; +identifier cb; +@@ +fp_ssm_start(ssm, cb) + +@@ +identifier ssm_callbacks.cb; +identifier ssm; +identifier dev; +identifier user_data; +@@ +void cb(FpSsm *ssm, FpDevice *dev, void* user_data ++ , GError *error + ) +{ ++ _Pragma("GCC warning \"Check that error is returned/free'ed properly!\""); + ... +} + diff --git a/cocci/10-driver.cocci b/cocci/10-driver.cocci new file mode 100644 index 0000000..cac0212 --- /dev/null +++ b/cocci/10-driver.cocci @@ -0,0 +1,386 @@ +@ orig_driver_struct @ +identifier driver_struct; +@@ +struct fp_img_driver driver_struct = { + ..., +}; + +// Grab the type of the main device struct using a rather blind fashion, +// and remove it from the init function. +// This assume that only device init calls fp_dev_set_instance_data, which +// is a fair assumption after all +@ orig_device_struct @ +type device_struct; +expression dev; +identifier dev_init; +identifier data; +@@ +dev_init(...) +{ + // Note: We redefine it to an instance access for now, which will be + // made to work correctly with a later transform/cast. +... + device_struct *data; +... +( +- data = g_malloc0(sizeof(*data)); ++ data = FP_INSTANCE_DATA(dev); +| +- data = (device_struct*) g_malloc0(sizeof(*data)); ++ data = FP_INSTANCE_DATA(dev); +| +- data = g_malloc0(sizeof(device_struct)); ++ data = FP_INSTANCE_DATA(dev); +) +... +- fp_dev_set_instance_data(dev, data); +... +} + +@ driver_ids @ +typedef FpIdEntry; +identifier driver_id_table; +@@ +-const struct usb_id driver_id_table[] = { ++const FpIdEntry driver_id_table[] = { + ... +}; + + +@ @ +identifier driver_ids.driver_id_table; +expression entry_vid; +expression entry_pid; +@@ +const FpIdEntry driver_id_table[] = { + ..., { +- .vendor = entry_vid, .product = entry_pid, ++ .vid = entry_vid, .pid = entry_pid, + }, ... +}; + +@ @ +identifier driver_ids.driver_id_table; +expression entry_vid; +expression entry_pid; +expression entry_data; +@@ +const FpIdEntry driver_id_table[] = { + ..., { +- .vendor = entry_vid, .product = entry_pid, .device_data = entry_data ++ .vid = entry_vid, .pid = entry_pid, .driver_data = entry_data + }, ... +}; + +@ @ +identifier driver_ids.driver_id_table; +expression entry_vid; +expression entry_pid; +expression entry_data; +@@ +const FpIdEntry driver_id_table[] = { + ..., { +- entry_vid, entry_pid, entry_data ++ .vid = entry_vid, .pid = entry_pid, .driver_data = entry_data + }, ... +}; + + + +@ driver_info extends orig_driver_struct @ +expression driver_full_name; +identifier driver_id_table; +identifier dev_open; +identifier dev_close; +identifier dev_scan_type; +@@ +struct fp_img_driver driver_struct = { + .driver = { + .full_name = driver_full_name, + .id_table = driver_id_table, + .scan_type = dev_scan_type, + }, + + .open = dev_open, + .close = dev_close, +}; + +@ script:python driver_gobj @ +driver_struct << orig_driver_struct.driver_struct; + +driver_id; +driver_init; +driver_cls; +_driver_cls; +driver_klass; +driver_class_init; +driver_ns; +driver_cast; +driver_cast_no_prefix; +@@ + +import os + +driver_id = driver_struct.split('_')[:-1] + +driver_cls = "FpDevice" + "".join(d[0].upper() + d[1:] for d in driver_id) +driver_id = '_'.join(driver_id) + +driver_ns = "fp_device_" + driver_id +driver_cast = driver_ns.upper() +driver_cast_no_prefix = driver_ns.upper()[3:] + +coccinelle.driver_id = cocci.make_expr('"%s"' % driver_id) +coccinelle.driver_cls = cocci.make_type(driver_cls) +coccinelle._driver_cls = cocci.make_type('struct _' + driver_cls) +coccinelle.driver_klass = cocci.make_type(driver_cls + 'Class') +coccinelle.driver_ns = cocci.make_ident(driver_ns) +coccinelle.driver_init = cocci.make_ident(driver_ns + '_init') +coccinelle.driver_class_init = cocci.make_ident(driver_ns + '_class_init') +coccinelle.driver_cast = cocci.make_ident(driver_cast) +coccinelle.driver_cast_no_prefix = cocci.make_ident(driver_cast_no_prefix) + +############################################################################# + +@ driver @ +typedef FpDeviceClass; +typedef FpImageDeviceClass; + +type orig_device_struct.device_struct; + +identifier orig_driver_struct.driver_struct; + +expression driver_gobj.driver_id; +identifier driver_gobj.driver_ns; +identifier driver_gobj.driver_init; +identifier driver_gobj.driver_class_init; +identifier driver_gobj.driver_cast; +identifier driver_gobj.driver_cast_no_prefix; +type driver_gobj.driver_cls; +type driver_gobj._driver_cls; +type driver_gobj.driver_klass; + +expression driver_info.driver_full_name; +identifier driver_info.driver_id_table; +identifier driver_info.dev_open; +identifier driver_info.dev_close; +identifier driver_info.dev_scan_type; +@@ +struct fp_img_driver driver_struct = { + ... +}; + ++static void ++driver_init(driver_cls *self) ++{ ++} ++ ++static void ++driver_class_init(driver_klass *klass) ++{ ++ FpDeviceClass *dev_class = FP_DEVICE_CLASS (klass); ++ FpImageDeviceClass *img_class = FP_IMAGE_DEVICE_CLASS (klass); ++ ++ dev_class->id = driver_id; ++ dev_class->full_name = driver_full_name; ++ dev_class->type = FP_DEVICE_TYPE_USB; ++ dev_class->id_table = driver_id_table; ++ dev_class->scan_type = dev_scan_type; ++ ++ img_class->img_open = dev_open; ++ img_class->img_close = dev_close; ++ IMG_CLASS_FUNCS; ++} + +///////////////////////////////////////////////////////////////////////// +@ optional_activate extends driver @ +identifier dev_activate; +@@ +struct fp_img_driver driver_struct = { +- .activate = dev_activate, +}; +@@ +identifier optional_activate.dev_activate; +@@ ++ img_class->activate = dev_activate; + IMG_CLASS_FUNCS; + +///////////////////////////////////////////////////////////////////////// +@ optional_deactivate extends driver @ +identifier dev_deactivate; +@@ +struct fp_img_driver driver_struct = { +- .deactivate = dev_deactivate, +}; +@@ +identifier optional_deactivate.dev_deactivate; +@@ ++ img_class->deactivate = dev_deactivate; + IMG_CLASS_FUNCS; + +///////////////////////////////////////////////////////////////////////// +@ optional_change_state extends driver @ +identifier dev_change_state; +@@ +struct fp_img_driver driver_struct = { +- .change_state = dev_change_state, +}; +@@ +identifier optional_change_state.dev_change_state; +@@ ++ img_class->change_state = dev_change_state; + IMG_CLASS_FUNCS; + +///////////////////////////////////////////////////////////////////////// +@ optional_bz3 extends driver @ +expression dev_bz3_threshold; +@@ +struct fp_img_driver driver_struct = { +- .bz3_threshold = dev_bz3_threshold, +}; +@@ +expression optional_bz3.dev_bz3_threshold; +@@ ++ ++ img_class->bz3_threshold = dev_bz3_threshold; + IMG_CLASS_FUNCS; + +///////////////////////////////////////////////////////////////////////// +@ optional_img_size extends driver @ +expression dev_img_width; +expression dev_img_height; +@@ +struct fp_img_driver driver_struct = { +- .img_width = dev_img_width, +- .img_height = dev_img_height, +}; +@@ +expression optional_img_size.dev_img_width; +expression optional_img_size.dev_img_height; +@@ ++ ++ img_class->img_width = dev_img_width; ++ img_class->img_height = dev_img_height; + IMG_CLASS_FUNCS; + +@ remove_placeholder extends driver @ +@@ +- IMG_CLASS_FUNCS; + +@ remove_orig extends driver @ +@@ +-struct fp_img_driver driver_struct = { +- ... +-}; + +///////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////// +@ type_declaration extends driver @ +@@ +-device_struct { ++_driver_cls { ++ FpImageDevice parent; ++ + ... +}; ++#include "TYPE_DECLARATION" + +@ extends driver @ +@@ +-#include "TYPE_DECLARATION" + ++G_DECLARE_FINAL_TYPE (driver_cls, driver_ns, FP, driver_cast_no_prefix, FpImageDevice); ++G_DEFINE_TYPE (driver_cls, driver_ns, FP_TYPE_IMAGE_DEVICE); + + +/////////////// +// Change some function declarations +@ extends driver @ +identifier a_driver_data; +@@ +-int ++void +dev_open(... +- ,unsigned long a_driver_data + ) { ... } + +@ extends driver @ +@@ +-int ++void +dev_activate(...) { ... } + + +///////////////////////////////////////////////////////////////////////// +// Replace all old data with a cast to the new class +///////////////////////////////////////////////////////////////////////// +@ rewrite_dev_struct extends driver @ +identifier func; +identifier data; +identifier dev; +@@ +func(...) +{ + ... +( +- device_struct *data; ++ driver_cls *self; + ... +( +- data = FP_INSTANCE_DATA(FP_DEVICE(dev)); ++ data = driver_cast(dev); +| +- data = FP_INSTANCE_DATA(dev); ++ data = driver_cast(dev); +) +| +- device_struct *data = FP_INSTANCE_DATA(FP_DEVICE(dev)); ++ driver_cls *self = driver_cast(dev); +| +- device_struct *data = FP_INSTANCE_DATA(dev); ++ driver_cls *self = driver_cast(dev); +) + ... +} + +@@ +identifier rewrite_dev_struct.func; +identifier rewrite_dev_struct.data; +@@ +func(...) +{ + <... +- data ++ self + ...> +} + +@ extends driver @ +identifier func; +identifier data; +@@ +func(..., +- device_struct *data, ++ driver_cls *self, +...) +{ + <... +- data ++ self + ...> +} + +// Remove unneccessary self check +@@ +@@ +-if (self != NULL) { + ... +-} + +// Remove g_free(self) +@@ +@@ +-g_free(self); + + + diff --git a/cocci/99-insert-checking-code.cocci b/cocci/99-insert-checking-code.cocci new file mode 100644 index 0000000..b830f20 --- /dev/null +++ b/cocci/99-insert-checking-code.cocci @@ -0,0 +1,38 @@ +// If we have matches on error conditions, the we likely have a memory +// mangement error. +@ forall @ +identifier error; +statement S; +@@ +if (<+... g_error_matches(error, ...) ...+>) { ++ _Pragma ("GCC error \"Inserted possibly wrong g_error_free!\""); ++ if (error) ++ g_error_free (error); + ... +} else S + +@ forall @ +identifier error; +@@ +if (<+... g_error_matches(error, ...) ...+>) { ++ _Pragma ("GCC error \"Inserted possibly wrong g_error_free!\""); ++ if (error) ++ g_error_free (error); + ... +} + +@@ +expression transfer; +identifier r; +statement S; +@@ +( +- r = libusb_cancel_transfer(transfer); +- if (r < 0) S ++ _Pragma("GCC warning \"Removed libusb_cancel_transfer call!\""); ++ g_warning("USB transfer %p should be cancelled but was not due to a lack of code migration!", transfer); +| +- libusb_cancel_transfer(transfer); ++ _Pragma("GCC warning \"Removed libusb_cancel_transfer call!\""); ++ g_warning("USB transfer %p should be cancelled but was not due to a lack of code migration!", transfer); +) diff --git a/cocci/all.cocci b/cocci/all.cocci new file mode 100644 index 0000000..f031f41 --- /dev/null +++ b/cocci/all.cocci @@ -0,0 +1,19 @@ +# First some cleanups; some of these are required for the later stuff to work +00-misc-cleanups.cocci +01-endpoint.cocci +04-misc-renames.cocci +03-function-renames.cocci +02-type-renames.cocci + + +# GObject and "driver" defintion +10-driver.cocci + +# +07-libusb-fill.cocci +05-libusb-1.cocci +06-libusb-callback-1.cocci + +08-ssm.cocci + +99-insert-checking-code.cocci diff --git a/cocci/apply-all b/cocci/apply-all new file mode 100755 index 0000000..f2e7f48 --- /dev/null +++ b/cocci/apply-all @@ -0,0 +1,9 @@ +#!/bin/sh + +pushd $( dirname "$0" ) +all="all.cocci" +real="/tmp/real.cocci" +cat "$all" | grep -P '^(?!#).+' | xargs cat >$real || exit 1 +popd + +spatch --sp-file $real "$@"