SONY_BLUETOOTH,
SONY_WWAN,
SONY_WIMAX,
- SONY_RFKILL_MAX,
+ N_SONY_RFKILL,
};
-static struct rfkill *sony_rfkill_devices[SONY_RFKILL_MAX];
-static int sony_rfkill_address[SONY_RFKILL_MAX] = {0x300, 0x500, 0x700, 0x900};
+static struct rfkill *sony_rfkill_devices[N_SONY_RFKILL];
+static int sony_rfkill_address[N_SONY_RFKILL] = {0x300, 0x500, 0x700, 0x900};
static void sony_nc_rfkill_update(void);
/*********** Input Devices ***********/
void *context, void **return_value)
{
struct acpi_device_info *info;
- struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
-
- if (ACPI_SUCCESS(acpi_get_object_info(handle, &buffer))) {
- info = buffer.pointer;
+ if (ACPI_SUCCESS(acpi_get_object_info(handle, &info))) {
printk(KERN_WARNING DRV_PFX "method: name: %4.4s, args %X\n",
(char *)&info->name, info->param_count);
- kfree(buffer.pointer);
+ kfree(info);
}
return AE_OK;
/* set the last requested brightness level */
if (sony_backlight_device &&
- !sony_backlight_update_status(sony_backlight_device))
+ sony_backlight_update_status(sony_backlight_device) < 0)
printk(KERN_WARNING DRV_PFX "unable to restore brightness level\n");
+ /* re-read rfkill state */
+ sony_nc_rfkill_update();
+
return 0;
}
{
int i;
- for (i = 0; i < SONY_RFKILL_MAX; i++) {
- if (sony_rfkill_devices[i])
+ for (i = 0; i < N_SONY_RFKILL; i++) {
+ if (sony_rfkill_devices[i]) {
rfkill_unregister(sony_rfkill_devices[i]);
+ rfkill_destroy(sony_rfkill_devices[i]);
+ }
}
}
-static int sony_nc_rfkill_get(void *data, enum rfkill_state *state)
-{
- int result;
- int argument = sony_rfkill_address[(long) data];
-
- sony_call_snc_handle(0x124, 0x200, &result);
- if (result & 0x1) {
- sony_call_snc_handle(0x124, argument, &result);
- if (result & 0xf)
- *state = RFKILL_STATE_UNBLOCKED;
- else
- *state = RFKILL_STATE_SOFT_BLOCKED;
- } else {
- *state = RFKILL_STATE_HARD_BLOCKED;
- }
-
- return 0;
-}
-
-static int sony_nc_rfkill_set(void *data, enum rfkill_state state)
+static int sony_nc_rfkill_set(void *data, bool blocked)
{
int result;
int argument = sony_rfkill_address[(long) data] + 0x100;
- if (state == RFKILL_STATE_UNBLOCKED)
+ if (!blocked)
argument |= 0xff0000;
return sony_call_snc_handle(0x124, argument, &result);
}
-static int sony_nc_setup_wifi_rfkill(struct acpi_device *device)
-{
- int err = 0;
- struct rfkill *sony_wifi_rfkill;
-
- sony_wifi_rfkill = rfkill_allocate(&device->dev, RFKILL_TYPE_WLAN);
- if (!sony_wifi_rfkill)
- return -1;
- sony_wifi_rfkill->name = "sony-wifi";
- sony_wifi_rfkill->toggle_radio = sony_nc_rfkill_set;
- sony_wifi_rfkill->get_state = sony_nc_rfkill_get;
- sony_wifi_rfkill->user_claim_unsupported = 1;
- sony_wifi_rfkill->data = (void *)SONY_WIFI;
- err = rfkill_register(sony_wifi_rfkill);
- if (err)
- rfkill_free(sony_wifi_rfkill);
- else
- sony_rfkill_devices[SONY_WIFI] = sony_wifi_rfkill;
- return err;
-}
+static const struct rfkill_ops sony_rfkill_ops = {
+ .set_block = sony_nc_rfkill_set,
+};
-static int sony_nc_setup_bluetooth_rfkill(struct acpi_device *device)
+static int sony_nc_setup_rfkill(struct acpi_device *device,
+ enum sony_nc_rfkill nc_type)
{
int err = 0;
- struct rfkill *sony_bluetooth_rfkill;
-
- sony_bluetooth_rfkill = rfkill_allocate(&device->dev,
- RFKILL_TYPE_BLUETOOTH);
- if (!sony_bluetooth_rfkill)
- return -1;
- sony_bluetooth_rfkill->name = "sony-bluetooth";
- sony_bluetooth_rfkill->toggle_radio = sony_nc_rfkill_set;
- sony_bluetooth_rfkill->get_state = sony_nc_rfkill_get;
- sony_bluetooth_rfkill->user_claim_unsupported = 1;
- sony_bluetooth_rfkill->data = (void *)SONY_BLUETOOTH;
- err = rfkill_register(sony_bluetooth_rfkill);
- if (err)
- rfkill_free(sony_bluetooth_rfkill);
- else
- sony_rfkill_devices[SONY_BLUETOOTH] = sony_bluetooth_rfkill;
- return err;
-}
+ struct rfkill *rfk;
+ enum rfkill_type type;
+ const char *name;
+ int result;
+ bool hwblock;
-static int sony_nc_setup_wwan_rfkill(struct acpi_device *device)
-{
- int err = 0;
- struct rfkill *sony_wwan_rfkill;
+ switch (nc_type) {
+ case SONY_WIFI:
+ type = RFKILL_TYPE_WLAN;
+ name = "sony-wifi";
+ break;
+ case SONY_BLUETOOTH:
+ type = RFKILL_TYPE_BLUETOOTH;
+ name = "sony-bluetooth";
+ break;
+ case SONY_WWAN:
+ type = RFKILL_TYPE_WWAN;
+ name = "sony-wwan";
+ break;
+ case SONY_WIMAX:
+ type = RFKILL_TYPE_WIMAX;
+ name = "sony-wimax";
+ break;
+ default:
+ return -EINVAL;
+ }
- sony_wwan_rfkill = rfkill_allocate(&device->dev, RFKILL_TYPE_WWAN);
- if (!sony_wwan_rfkill)
- return -1;
- sony_wwan_rfkill->name = "sony-wwan";
- sony_wwan_rfkill->toggle_radio = sony_nc_rfkill_set;
- sony_wwan_rfkill->get_state = sony_nc_rfkill_get;
- sony_wwan_rfkill->user_claim_unsupported = 1;
- sony_wwan_rfkill->data = (void *)SONY_WWAN;
- err = rfkill_register(sony_wwan_rfkill);
- if (err)
- rfkill_free(sony_wwan_rfkill);
- else
- sony_rfkill_devices[SONY_WWAN] = sony_wwan_rfkill;
- return err;
-}
+ rfk = rfkill_alloc(name, &device->dev, type,
+ &sony_rfkill_ops, (void *)nc_type);
+ if (!rfk)
+ return -ENOMEM;
-static int sony_nc_setup_wimax_rfkill(struct acpi_device *device)
-{
- int err = 0;
- struct rfkill *sony_wimax_rfkill;
+ sony_call_snc_handle(0x124, 0x200, &result);
+ hwblock = !(result & 0x1);
+ rfkill_set_hw_state(rfk, hwblock);
- sony_wimax_rfkill = rfkill_allocate(&device->dev, RFKILL_TYPE_WIMAX);
- if (!sony_wimax_rfkill)
- return -1;
- sony_wimax_rfkill->name = "sony-wimax";
- sony_wimax_rfkill->toggle_radio = sony_nc_rfkill_set;
- sony_wimax_rfkill->get_state = sony_nc_rfkill_get;
- sony_wimax_rfkill->user_claim_unsupported = 1;
- sony_wimax_rfkill->data = (void *)SONY_WIMAX;
- err = rfkill_register(sony_wimax_rfkill);
- if (err)
- rfkill_free(sony_wimax_rfkill);
- else
- sony_rfkill_devices[SONY_WIMAX] = sony_wimax_rfkill;
+ err = rfkill_register(rfk);
+ if (err) {
+ rfkill_destroy(rfk);
+ return err;
+ }
+ sony_rfkill_devices[nc_type] = rfk;
return err;
}
static void sony_nc_rfkill_update()
{
- int i;
- enum rfkill_state state;
+ enum sony_nc_rfkill i;
+ int result;
+ bool hwblock;
- for (i = 0; i < SONY_RFKILL_MAX; i++) {
- if (sony_rfkill_devices[i]) {
- sony_rfkill_devices[i]->
- get_state(sony_rfkill_devices[i]->data,
- &state);
- rfkill_force_state(sony_rfkill_devices[i], state);
+ sony_call_snc_handle(0x124, 0x200, &result);
+ hwblock = !(result & 0x1);
+
+ for (i = 0; i < N_SONY_RFKILL; i++) {
+ int argument = sony_rfkill_address[i];
+
+ if (!sony_rfkill_devices[i])
+ continue;
+
+ if (hwblock) {
+ if (rfkill_set_hw_state(sony_rfkill_devices[i], true)) {
+ /* we already know we're blocked */
+ }
+ continue;
}
+
+ sony_call_snc_handle(0x124, argument, &result);
+ rfkill_set_states(sony_rfkill_devices[i],
+ !(result & 0xf), false);
}
}
}
if (result & 0x1)
- sony_nc_setup_wifi_rfkill(device);
+ sony_nc_setup_rfkill(device, SONY_WIFI);
if (result & 0x2)
- sony_nc_setup_bluetooth_rfkill(device);
+ sony_nc_setup_rfkill(device, SONY_BLUETOOTH);
if (result & 0x1c)
- sony_nc_setup_wwan_rfkill(device);
+ sony_nc_setup_rfkill(device, SONY_WWAN);
if (result & 0x20)
- sony_nc_setup_wimax_rfkill(device);
+ sony_nc_setup_rfkill(device, SONY_WIMAX);
return 0;
}