• Home
  • Raw
  • Download

Lines Matching refs:device

135 	struct cras_bt_device *device;  member
168 struct cras_bt_device *device; in cras_bt_device_create() local
170 device = calloc(1, sizeof(*device)); in cras_bt_device_create()
171 if (device == NULL) in cras_bt_device_create()
174 device->conn = conn; in cras_bt_device_create()
175 device->object_path = strdup(object_path); in cras_bt_device_create()
176 if (device->object_path == NULL) { in cras_bt_device_create()
177 free(device); in cras_bt_device_create()
180 device->stable_id = in cras_bt_device_create()
181 SuperFastHash(device->object_path, strlen(device->object_path), in cras_bt_device_create()
182 strlen(device->object_path)); in cras_bt_device_create()
184 DL_APPEND(devices, device); in cras_bt_device_create()
186 return device; in cras_bt_device_create()
217 struct cras_bt_device *device, in cras_bt_device_connect_profile() argument
225 dbus_message_new_method_call(BLUEZ_SERVICE, device->object_path, in cras_bt_device_connect_profile()
256 struct cras_bt_device *device) in cras_bt_device_disconnect() argument
263 dbus_message_new_method_call(BLUEZ_SERVICE, device->object_path, in cras_bt_device_disconnect()
289 static void cras_bt_device_destroy(struct cras_bt_device *device) in cras_bt_device_destroy() argument
292 DL_DELETE(devices, device); in cras_bt_device_destroy()
294 if (device->conn_watch_timer) in cras_bt_device_destroy()
295 cras_tm_cancel_timer(tm, device->conn_watch_timer); in cras_bt_device_destroy()
296 if (device->switch_profile_timer) in cras_bt_device_destroy()
297 cras_tm_cancel_timer(tm, device->switch_profile_timer); in cras_bt_device_destroy()
298 if (device->suspend_timer) in cras_bt_device_destroy()
299 cras_tm_cancel_timer(tm, device->suspend_timer); in cras_bt_device_destroy()
300 free(device->adapter_obj_path); in cras_bt_device_destroy()
301 free(device->object_path); in cras_bt_device_destroy()
302 free(device->address); in cras_bt_device_destroy()
303 free(device->name); in cras_bt_device_destroy()
304 free(device); in cras_bt_device_destroy()
307 void cras_bt_device_remove(struct cras_bt_device *device) in cras_bt_device_remove() argument
314 if (device->connected) in cras_bt_device_remove()
316 device->connected_profiles); in cras_bt_device_remove()
321 cras_a2dp_suspend_connected_device(device); in cras_bt_device_remove()
322 cras_hfp_ag_suspend_connected_device(device); in cras_bt_device_remove()
323 cras_bt_device_destroy(device); in cras_bt_device_remove()
337 struct cras_bt_device *device; in cras_bt_device_get() local
339 DL_FOREACH (devices, device) { in cras_bt_device_get()
340 if (strcmp(device->object_path, object_path) == 0) in cras_bt_device_get()
341 return device; in cras_bt_device_get()
347 const char *cras_bt_device_object_path(const struct cras_bt_device *device) in cras_bt_device_object_path() argument
349 return device->object_path; in cras_bt_device_object_path()
352 int cras_bt_device_get_stable_id(const struct cras_bt_device *device) in cras_bt_device_get_stable_id() argument
354 return device->stable_id; in cras_bt_device_get_stable_id()
358 cras_bt_device_adapter(const struct cras_bt_device *device) in cras_bt_device_adapter() argument
360 return cras_bt_adapter_get(device->adapter_obj_path); in cras_bt_device_adapter()
363 const char *cras_bt_device_address(const struct cras_bt_device *device) in cras_bt_device_address() argument
365 return device->address; in cras_bt_device_address()
368 const char *cras_bt_device_name(const struct cras_bt_device *device) in cras_bt_device_name() argument
370 return device->name; in cras_bt_device_name()
373 int cras_bt_device_paired(const struct cras_bt_device *device) in cras_bt_device_paired() argument
375 return device->paired; in cras_bt_device_paired()
378 int cras_bt_device_trusted(const struct cras_bt_device *device) in cras_bt_device_trusted() argument
380 return device->trusted; in cras_bt_device_trusted()
383 int cras_bt_device_connected(const struct cras_bt_device *device) in cras_bt_device_connected() argument
385 return device->connected; in cras_bt_device_connected()
388 int cras_bt_device_supports_profile(const struct cras_bt_device *device, in cras_bt_device_supports_profile() argument
391 return !!(device->profiles & profile); in cras_bt_device_supports_profile()
394 void cras_bt_device_append_iodev(struct cras_bt_device *device, in cras_bt_device_append_iodev() argument
400 bt_iodev = device->bt_iodevs[iodev->direction]; in cras_bt_device_append_iodev()
405 device->bt_iodevs[iodev->direction] = in cras_bt_device_append_iodev()
406 cras_bt_io_create(device, iodev, profile); in cras_bt_device_append_iodev()
415 static void bt_device_set_nodes_plugged(struct cras_bt_device *device, in bt_device_set_nodes_plugged() argument
420 iodev = device->bt_iodevs[CRAS_STREAM_INPUT]; in bt_device_set_nodes_plugged()
424 iodev = device->bt_iodevs[CRAS_STREAM_OUTPUT]; in bt_device_set_nodes_plugged()
429 static void bt_device_switch_profile(struct cras_bt_device *device,
433 void cras_bt_device_rm_iodev(struct cras_bt_device *device, in cras_bt_device_rm_iodev() argument
439 bt_device_set_nodes_plugged(device, 0); in cras_bt_device_rm_iodev()
441 bt_iodev = device->bt_iodevs[iodev->direction]; in cras_bt_device_rm_iodev()
455 device->active_profile = try_profile; in cras_bt_device_rm_iodev()
456 bt_device_switch_profile(device, bt_iodev, 0); in cras_bt_device_rm_iodev()
468 device->bt_iodevs[iodev->direction] = NULL; in cras_bt_device_rm_iodev()
471 if (!device->bt_iodevs[CRAS_STREAM_INPUT] && in cras_bt_device_rm_iodev()
472 !device->bt_iodevs[CRAS_STREAM_OUTPUT]) in cras_bt_device_rm_iodev()
473 cras_bt_device_set_active_profile(device, 0); in cras_bt_device_rm_iodev()
476 void cras_bt_device_a2dp_configured(struct cras_bt_device *device) in cras_bt_device_a2dp_configured() argument
478 BTLOG(btlog, BT_A2DP_CONFIGURED, device->connected_profiles, 0); in cras_bt_device_a2dp_configured()
479 device->connected_profiles |= CRAS_BT_DEVICE_PROFILE_A2DP_SINK; in cras_bt_device_a2dp_configured()
482 int cras_bt_device_has_a2dp(struct cras_bt_device *device) in cras_bt_device_has_a2dp() argument
484 struct cras_iodev *odev = device->bt_iodevs[CRAS_STREAM_OUTPUT]; in cras_bt_device_has_a2dp()
491 int cras_bt_device_can_switch_to_a2dp(struct cras_bt_device *device) in cras_bt_device_can_switch_to_a2dp() argument
493 struct cras_iodev *idev = device->bt_iodevs[CRAS_STREAM_INPUT]; in cras_bt_device_can_switch_to_a2dp()
495 return cras_bt_device_has_a2dp(device) && in cras_bt_device_can_switch_to_a2dp()
499 static void bt_device_remove_conflict(struct cras_bt_device *device) in bt_device_remove_conflict() argument
504 cras_hfp_ag_remove_conflict(device); in bt_device_remove_conflict()
508 if (connected && (connected != device)) in bt_device_remove_conflict()
514 int cras_bt_device_audio_gateway_initialized(struct cras_bt_device *device) in cras_bt_device_audio_gateway_initialized() argument
516 BTLOG(btlog, BT_AUDIO_GATEWAY_INIT, device->profiles, 0); in cras_bt_device_audio_gateway_initialized()
519 device->connected_profiles |= (CRAS_BT_DEVICE_PROFILE_HFP_HANDSFREE | in cras_bt_device_audio_gateway_initialized()
526 device, CRAS_BT_DEVICE_PROFILE_HFP_HANDSFREE)) { in cras_bt_device_audio_gateway_initialized()
528 device->profiles | CRAS_BT_DEVICE_PROFILE_HFP_HANDSFREE; in cras_bt_device_audio_gateway_initialized()
529 cras_bt_device_set_supported_profiles(device, profiles); in cras_bt_device_audio_gateway_initialized()
530 device->hidden_profiles |= CRAS_BT_DEVICE_PROFILE_HFP_HANDSFREE; in cras_bt_device_audio_gateway_initialized()
531 bt_device_conn_watch_cb(NULL, (void *)device); in cras_bt_device_audio_gateway_initialized()
538 cras_bt_device_get_active_profile(const struct cras_bt_device *device) in cras_bt_device_get_active_profile() argument
540 return device->active_profile; in cras_bt_device_get_active_profile()
543 void cras_bt_device_set_active_profile(struct cras_bt_device *device, in cras_bt_device_set_active_profile() argument
546 device->active_profile = profile; in cras_bt_device_set_active_profile()
549 static void cras_bt_device_log_profile(const struct cras_bt_device *device, in cras_bt_device_log_profile() argument
555 device->address); in cras_bt_device_log_profile()
559 device->address); in cras_bt_device_log_profile()
563 device->address); in cras_bt_device_log_profile()
567 device->address); in cras_bt_device_log_profile()
571 device->address); in cras_bt_device_log_profile()
575 device->address); in cras_bt_device_log_profile()
579 device->address); in cras_bt_device_log_profile()
583 device->address); in cras_bt_device_log_profile()
588 static void cras_bt_device_log_profiles(const struct cras_bt_device *device, in cras_bt_device_log_profiles() argument
596 cras_bt_device_log_profile(device, profile); in cras_bt_device_log_profiles()
602 cras_bt_device_is_profile_connected(const struct cras_bt_device *device, in cras_bt_device_is_profile_connected() argument
605 return !!(device->connected_profiles & profile); in cras_bt_device_is_profile_connected()
609 bt_device_schedule_suspend(struct cras_bt_device *device, unsigned int msec,
616 struct cras_bt_device *device = (struct cras_bt_device *)arg; in bt_device_conn_watch_cb() local
623 BTLOG(btlog, BT_DEV_CONN_WATCH_CB, device->conn_watch_retries, in bt_device_conn_watch_cb()
624 device->profiles); in bt_device_conn_watch_cb()
625 device->conn_watch_timer = NULL; in bt_device_conn_watch_cb()
628 if (!device->profiles) in bt_device_conn_watch_cb()
632 device, CRAS_BT_DEVICE_PROFILE_A2DP_SINK); in bt_device_conn_watch_cb()
634 device, CRAS_BT_DEVICE_PROFILE_A2DP_SINK); in bt_device_conn_watch_cb()
636 device, CRAS_BT_DEVICE_PROFILE_HFP_HANDSFREE); in bt_device_conn_watch_cb()
638 device, CRAS_BT_DEVICE_PROFILE_HFP_HANDSFREE); in bt_device_conn_watch_cb()
650 cras_bt_device_connect_profile(device->conn, device, in bt_device_conn_watch_cb()
653 cras_bt_device_connect_profile(device->conn, device, in bt_device_conn_watch_cb()
666 bt_device_remove_conflict(device); in bt_device_conn_watch_cb()
669 device, CRAS_BT_DEVICE_PROFILE_A2DP_SINK)) in bt_device_conn_watch_cb()
670 cras_a2dp_start(device); in bt_device_conn_watch_cb()
673 device, CRAS_BT_DEVICE_PROFILE_HFP_HANDSFREE)) { in bt_device_conn_watch_cb()
674 rc = cras_hfp_ag_start(device); in bt_device_conn_watch_cb()
678 bt_device_schedule_suspend(device, 0, in bt_device_conn_watch_cb()
682 bt_device_set_nodes_plugged(device, 1); in bt_device_conn_watch_cb()
687 syslog(LOG_DEBUG, "conn_watch_retries: %d", device->conn_watch_retries); in bt_device_conn_watch_cb()
689 if (--device->conn_watch_retries) { in bt_device_conn_watch_cb()
691 device->conn_watch_timer = in bt_device_conn_watch_cb()
693 bt_device_conn_watch_cb, device); in bt_device_conn_watch_cb()
696 bt_device_schedule_suspend(device, 0, CONN_WATCH_TIME_OUT); in bt_device_conn_watch_cb()
701 cras_bt_device_start_new_conn_watch_timer(struct cras_bt_device *device) in cras_bt_device_start_new_conn_watch_timer() argument
705 if (device->conn_watch_timer) { in cras_bt_device_start_new_conn_watch_timer()
706 cras_tm_cancel_timer(tm, device->conn_watch_timer); in cras_bt_device_start_new_conn_watch_timer()
708 device->conn_watch_retries = CONN_WATCH_MAX_RETRIES; in cras_bt_device_start_new_conn_watch_timer()
709 device->conn_watch_timer = cras_tm_create_timer( in cras_bt_device_start_new_conn_watch_timer()
710 tm, CONN_WATCH_PERIOD_MS, bt_device_conn_watch_cb, device); in cras_bt_device_start_new_conn_watch_timer()
713 static void bt_device_cancel_suspend(struct cras_bt_device *device);
715 void cras_bt_device_set_connected(struct cras_bt_device *device, int value) in cras_bt_device_set_connected() argument
718 if (!device->connected && value) { in cras_bt_device_set_connected()
719 BTLOG(btlog, BT_DEV_CONNECTED, device->profiles, in cras_bt_device_set_connected()
720 device->stable_id); in cras_bt_device_set_connected()
723 if (device->connected && !value) { in cras_bt_device_set_connected()
724 BTLOG(btlog, BT_DEV_DISCONNECTED, device->profiles, in cras_bt_device_set_connected()
725 device->stable_id); in cras_bt_device_set_connected()
726 cras_bt_profile_on_device_disconnected(device); in cras_bt_device_set_connected()
729 device->connected_profiles = 0; in cras_bt_device_set_connected()
730 bt_device_cancel_suspend(device); in cras_bt_device_set_connected()
733 device->connected = value; in cras_bt_device_set_connected()
735 if (!device->connected && device->conn_watch_timer) { in cras_bt_device_set_connected()
736 cras_tm_cancel_timer(tm, device->conn_watch_timer); in cras_bt_device_set_connected()
737 device->conn_watch_timer = NULL; in cras_bt_device_set_connected()
741 void cras_bt_device_notify_profile_dropped(struct cras_bt_device *device, in cras_bt_device_notify_profile_dropped() argument
744 device->connected_profiles &= ~profile; in cras_bt_device_notify_profile_dropped()
747 if (!device->connected) in cras_bt_device_notify_profile_dropped()
755 bt_device_schedule_suspend(device, PROFILE_DROP_SUSPEND_DELAY_MS, in cras_bt_device_notify_profile_dropped()
768 int cras_bt_device_set_supported_profiles(struct cras_bt_device *device, in cras_bt_device_set_supported_profiles() argument
772 if ((device->profiles & profiles) == profiles) in cras_bt_device_set_supported_profiles()
775 unsigned int new_profiles = profiles & ~device->profiles; in cras_bt_device_set_supported_profiles()
779 if (device->connected && (new_profiles & CRAS_SUPPORTED_PROFILES)) in cras_bt_device_set_supported_profiles()
781 device->profiles, new_profiles); in cras_bt_device_set_supported_profiles()
782 cras_bt_device_log_profiles(device, new_profiles); in cras_bt_device_set_supported_profiles()
783 device->profiles = profiles | device->hidden_profiles; in cras_bt_device_set_supported_profiles()
788 void cras_bt_device_update_properties(struct cras_bt_device *device, in cras_bt_device_update_properties() argument
814 free(device->adapter_obj_path); in cras_bt_device_update_properties()
815 device->adapter_obj_path = strdup(value); in cras_bt_device_update_properties()
817 free(device->address); in cras_bt_device_update_properties()
818 device->address = strdup(value); in cras_bt_device_update_properties()
820 free(device->name); in cras_bt_device_update_properties()
821 device->name = strdup(value); in cras_bt_device_update_properties()
830 device->bluetooth_class = value; in cras_bt_device_update_properties()
838 device->paired = value; in cras_bt_device_update_properties()
840 device->trusted = value; in cras_bt_device_update_properties()
842 cras_bt_device_set_connected(device, value); in cras_bt_device_update_properties()
843 watch_needed = device->connected && in cras_bt_device_update_properties()
845 device, in cras_bt_device_update_properties()
875 if (cras_bt_device_set_supported_profiles(device, in cras_bt_device_update_properties()
877 watch_needed = device->connected; in cras_bt_device_update_properties()
891 free(device->adapter_obj_path); in cras_bt_device_update_properties()
892 device->adapter_obj_path = NULL; in cras_bt_device_update_properties()
894 free(device->address); in cras_bt_device_update_properties()
895 device->address = NULL; in cras_bt_device_update_properties()
897 free(device->name); in cras_bt_device_update_properties()
898 device->name = NULL; in cras_bt_device_update_properties()
900 device->bluetooth_class = 0; in cras_bt_device_update_properties()
902 device->paired = 0; in cras_bt_device_update_properties()
904 device->trusted = 0; in cras_bt_device_update_properties()
906 device->connected = 0; in cras_bt_device_update_properties()
908 device->profiles = device->hidden_profiles; in cras_bt_device_update_properties()
915 cras_bt_device_start_new_conn_watch_timer(device); in cras_bt_device_update_properties()
975 int cras_bt_device_sco_connect(struct cras_bt_device *device, int codec) in cras_bt_device_sco_connect() argument
983 adapter = cras_bt_device_adapter(device); in cras_bt_device_sco_connect()
986 cras_bt_device_object_path(device)); in cras_bt_device_sco_connect()
1012 if (bt_address(cras_bt_device_address(device), &addr)) in cras_bt_device_sco_connect()
1045 bt_device_schedule_suspend(device, SCO_SUSPEND_DELAY_MS, in cras_bt_device_sco_connect()
1062 int cras_bt_device_sco_packet_size(struct cras_bt_device *device, in cras_bt_device_sco_packet_size() argument
1071 adapter = cras_bt_adapter_get(device->adapter_obj_path); in cras_bt_device_sco_packet_size()
1095 void cras_bt_device_set_use_hardware_volume(struct cras_bt_device *device, in cras_bt_device_set_use_hardware_volume() argument
1100 device->use_hardware_volume = use_hardware_volume; in cras_bt_device_set_use_hardware_volume()
1101 iodev = device->bt_iodevs[CRAS_STREAM_OUTPUT]; in cras_bt_device_set_use_hardware_volume()
1106 int cras_bt_device_get_use_hardware_volume(struct cras_bt_device *device) in cras_bt_device_get_use_hardware_volume() argument
1108 return device->use_hardware_volume; in cras_bt_device_get_use_hardware_volume()
1113 struct cras_bt_device *device, in init_bt_device_msg() argument
1121 msg->device = device; in init_bt_device_msg()
1127 int cras_bt_device_cancel_suspend(struct cras_bt_device *device) in cras_bt_device_cancel_suspend() argument
1132 init_bt_device_msg(&msg, BT_DEVICE_CANCEL_SUSPEND, device, NULL, 0, 0); in cras_bt_device_cancel_suspend()
1138 struct cras_bt_device *device, unsigned int msec, in cras_bt_device_schedule_suspend() argument
1144 init_bt_device_msg(&msg, BT_DEVICE_SCHEDULE_SUSPEND, device, NULL, msec, in cras_bt_device_schedule_suspend()
1172 int cras_bt_device_switch_profile_enable_dev(struct cras_bt_device *device, in cras_bt_device_switch_profile_enable_dev() argument
1178 init_bt_device_msg(&msg, BT_DEVICE_SWITCH_PROFILE_ENABLE_DEV, device, in cras_bt_device_switch_profile_enable_dev()
1184 int cras_bt_device_switch_profile(struct cras_bt_device *device, in cras_bt_device_switch_profile() argument
1190 init_bt_device_msg(&msg, BT_DEVICE_SWITCH_PROFILE, device, bt_iodev, 0, in cras_bt_device_switch_profile()
1198 struct cras_bt_device *device = (struct cras_bt_device *)arg; in profile_switch_delay_cb() local
1201 device->switch_profile_timer = NULL; in profile_switch_delay_cb()
1202 iodev = device->bt_iodevs[CRAS_STREAM_OUTPUT]; in profile_switch_delay_cb()
1218 static void bt_device_switch_profile_with_delay(struct cras_bt_device *device, in bt_device_switch_profile_with_delay() argument
1223 if (device->switch_profile_timer) { in bt_device_switch_profile_with_delay()
1224 cras_tm_cancel_timer(tm, device->switch_profile_timer); in bt_device_switch_profile_with_delay()
1225 device->switch_profile_timer = NULL; in bt_device_switch_profile_with_delay()
1227 device->switch_profile_timer = cras_tm_create_timer( in bt_device_switch_profile_with_delay()
1228 tm, delay_ms, profile_switch_delay_cb, device); in bt_device_switch_profile_with_delay()
1234 static void bt_device_switch_profile(struct cras_bt_device *device, in bt_device_switch_profile() argument
1246 iodev = device->bt_iodevs[dir]; in bt_device_switch_profile()
1253 iodev = device->bt_iodevs[dir]; in bt_device_switch_profile()
1270 device, PROFILE_SWITCH_DELAY_MS); in bt_device_switch_profile()
1277 struct cras_bt_device *device = (struct cras_bt_device *)arg; in bt_device_suspend_cb() local
1279 BTLOG(btlog, BT_DEV_SUSPEND_CB, device->profiles, in bt_device_suspend_cb()
1280 device->suspend_reason); in bt_device_suspend_cb()
1281 device->suspend_timer = NULL; in bt_device_suspend_cb()
1284 switch (device->suspend_reason) { in bt_device_suspend_cb()
1305 cras_a2dp_suspend_connected_device(device); in bt_device_suspend_cb()
1306 cras_hfp_ag_suspend_connected_device(device); in bt_device_suspend_cb()
1307 cras_bt_device_disconnect(device->conn, device); in bt_device_suspend_cb()
1311 bt_device_schedule_suspend(struct cras_bt_device *device, unsigned int msec, in bt_device_schedule_suspend() argument
1316 if (device->suspend_timer) in bt_device_schedule_suspend()
1318 device->suspend_reason = suspend_reason; in bt_device_schedule_suspend()
1319 device->suspend_timer = in bt_device_schedule_suspend()
1320 cras_tm_create_timer(tm, msec, bt_device_suspend_cb, device); in bt_device_schedule_suspend()
1323 static void bt_device_cancel_suspend(struct cras_bt_device *device) in bt_device_cancel_suspend() argument
1326 if (device->suspend_timer == NULL) in bt_device_cancel_suspend()
1328 cras_tm_cancel_timer(tm, device->suspend_timer); in bt_device_cancel_suspend()
1329 device->suspend_timer = NULL; in bt_device_cancel_suspend()
1335 struct cras_bt_device *device = NULL; in bt_device_process_msg() local
1337 DL_FOREACH (devices, device) { in bt_device_process_msg()
1338 if (device == bt_msg->device) in bt_device_process_msg()
1343 if (device == NULL) in bt_device_process_msg()
1348 bt_device_switch_profile(bt_msg->device, bt_msg->dev, 0); in bt_device_process_msg()
1351 bt_device_switch_profile(bt_msg->device, bt_msg->dev, 1); in bt_device_process_msg()
1354 bt_device_schedule_suspend(bt_msg->device, bt_msg->arg1, in bt_device_process_msg()
1358 bt_device_cancel_suspend(bt_msg->device); in bt_device_process_msg()
1371 void cras_bt_device_update_hardware_volume(struct cras_bt_device *device, in cras_bt_device_update_hardware_volume() argument
1376 iodev = device->bt_iodevs[CRAS_STREAM_OUTPUT]; in cras_bt_device_update_hardware_volume()
1383 if (!cras_bt_device_get_use_hardware_volume(device)) in cras_bt_device_update_hardware_volume()
1390 int cras_bt_device_get_sco(struct cras_bt_device *device, int codec) in cras_bt_device_get_sco() argument
1392 if (device->sco_ref_count == 0) { in cras_bt_device_get_sco()
1393 device->sco_fd = cras_bt_device_sco_connect(device, codec); in cras_bt_device_get_sco()
1394 if (device->sco_fd < 0) in cras_bt_device_get_sco()
1395 return device->sco_fd; in cras_bt_device_get_sco()
1398 ++device->sco_ref_count; in cras_bt_device_get_sco()
1402 void cras_bt_device_put_sco(struct cras_bt_device *device) in cras_bt_device_put_sco() argument
1404 if (device->sco_ref_count == 0) in cras_bt_device_put_sco()
1407 if (--device->sco_ref_count == 0) in cras_bt_device_put_sco()
1408 close(device->sco_fd); in cras_bt_device_put_sco()